Merge branch 'master' into v1.4
This commit is contained in:
commit
decb35332b
|
@ -640,6 +640,11 @@ python-reconf:
|
|||
rm -f src/mod/languages/mod_python/Makefile
|
||||
./config.status
|
||||
|
||||
reconf:
|
||||
rm config.cache
|
||||
sh ./config.status --recheck
|
||||
sh ./config.status
|
||||
|
||||
srtp-reconf:
|
||||
cd libs/srtp && $(MAKE) clean
|
||||
cd libs/srtp && sh ./config.status --recheck
|
||||
|
|
|
@ -42,7 +42,7 @@ fi
|
|||
|
||||
|
||||
cd $FS_DIR/libs
|
||||
svn co https://opalvoip.svn.sourceforge.net/svnroot/opalvoip/ptlib/$PTLIB_VERSION ptlib
|
||||
svn co https://svn.code.sf.net/p/opalvoip/code/ptlib/$PTLIB_VERSION ptlib
|
||||
cd $FS_DIR/libs/ptlib
|
||||
# LDAP disabled due to conflict wit libs in spidermonkey
|
||||
./configure --disable-plugins --disable-openldap --prefix=$INSTALLDIR
|
||||
|
@ -50,7 +50,7 @@ ${MAKE}
|
|||
sudo ${MAKE} install
|
||||
|
||||
cd $FS_DIR/libs
|
||||
svn co https://opalvoip.svn.sourceforge.net/svnroot/opalvoip/opal/$OPAL_VERSION opal
|
||||
svn co https://svn.code.sf.net/p/opalvoip/code/opal/$OPAL_VERSION opal
|
||||
cd $FS_DIR/libs/opal
|
||||
./configure --disable-plugins --prefix=$INSTALLDIR
|
||||
$MAKE
|
||||
|
|
|
@ -105,6 +105,7 @@ event_handlers/mod_event_socket
|
|||
#event_handlers/mod_format_cdr
|
||||
#event_handlers/mod_json_cdr
|
||||
#event_handlers/mod_radius_cdr
|
||||
#event_handlers/mod_odbc_cdr
|
||||
#event_handlers/mod_rayo
|
||||
#event_handlers/mod_snmp
|
||||
formats/mod_local_stream
|
||||
|
@ -131,6 +132,7 @@ loggers/mod_syslog
|
|||
#say/mod_say_de
|
||||
say/mod_say_en
|
||||
#say/mod_say_es
|
||||
#say/mod_say_es_ar
|
||||
#say/mod_say_fa
|
||||
#say/mod_say_fr
|
||||
#say/mod_say_he
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
<settings>
|
||||
<!--Colorize the Console -->
|
||||
<param name="colorize-console" value="true"/>
|
||||
<!--Include full timestamps in dialplan logs -->
|
||||
<param name="dialplan-timestamps" value="false"/>
|
||||
<!--Most channels to allow at once -->
|
||||
<param name="max-sessions" value="1000"/>
|
||||
<!--Most channels to create per second -->
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
<settings>
|
||||
<!--Colorize the Console -->
|
||||
<param name="colorize-console" value="true"/>
|
||||
<!--Include full timestamps in dialplan logs -->
|
||||
<param name="dialplan-timestamps" value="false"/>
|
||||
<!--Most channels to allow at once -->
|
||||
<param name="max-sessions" value="1000"/>
|
||||
<!--Most channels to create per second -->
|
||||
|
|
|
@ -2,8 +2,14 @@
|
|||
|
||||
<!-- rayo params -->
|
||||
<settings>
|
||||
<!-- ends idle calls : unbridged calls that have not been controlled by client in some time -->
|
||||
<param name="max-idle-sec" value="300"/>
|
||||
<!-- conference profile to use for mixers- sla = shared line appearance / conference /w no audio -->
|
||||
<param name="mixer-conf-profile" value="sla"/>
|
||||
<!-- if true, to attribute in offer uses URI instead of name/number -->
|
||||
<param name="offer-uri" value="true"/>
|
||||
<!-- if true, channel variables are added to rayo client offer -->
|
||||
<param name="add-variables-to-offer" value="false"/>
|
||||
</settings>
|
||||
|
||||
<!-- record component params -->
|
||||
|
@ -52,8 +58,8 @@
|
|||
|
||||
<!-- map mod_spandsp call progress tone detector to Rayo CPA signal events. Fires DETECTED_TONE events until stopped. -->
|
||||
<detector name="mod_spandsp_tone">
|
||||
<start application="start_tone_detect" data="1"/>
|
||||
<stop application="stop_tone_detect" data=""/>
|
||||
<start application="spandsp_start_tone_detect" data="1"/>
|
||||
<stop application="spandsp_stop_tone_detect" data=""/>
|
||||
<!-- map tone events to Rayo CPA signal type -->
|
||||
<event class="CUSTOM" subclass="DETECTED_TONE" type-header="Detected-Tone">
|
||||
<signal-type header-value="SIT" value="sit"/>
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
<!-- Colorize the Console -->
|
||||
<param name="colorize-console" value="true"/>
|
||||
|
||||
<!--Include full timestamps in dialplan logs -->
|
||||
<param name="dialplan-timestamps" value="false"/>
|
||||
|
||||
<!-- Run the timer at 20ms by default and drop down as needed unless you set 1m-timer=true which was previous default -->
|
||||
<!-- <param name="1ms-timer" value="true"/> -->
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
<settings>
|
||||
<!--Colorize the Console -->
|
||||
<param name="colorize-console" value="true"/>
|
||||
<!--Include full timestamps in dialplan logs -->
|
||||
<param name="dialplan-timestamps" value="false"/>
|
||||
<!--Most channels to allow at once -->
|
||||
<param name="max-sessions" value="1000"/>
|
||||
<!--Most channels to create per second -->
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<configuration name="graylog2.conf" description="Graylog2 Logger">
|
||||
<!-- emerg - system is unusable -->
|
||||
<!-- alert - action must be taken immediately -->
|
||||
<!-- crit - critical conditions -->
|
||||
<!-- err - error conditions -->
|
||||
<!-- warning - warning conditions -->
|
||||
<!-- notice - normal, but significant, condition -->
|
||||
<!-- info - informational message -->
|
||||
<!-- debug - debug-level message -->
|
||||
<settings>
|
||||
<param name="server-host" value="192.168.0.69"/>
|
||||
<param name="server-port" value="12201"/>
|
||||
<param name="loglevel" value="warning"/>
|
||||
<!-- Uncomment if using logstash w/ gelf.rb -->
|
||||
<!--param name="send-uncompressed-header" value="true"/-->
|
||||
|
||||
<!-- fields to add to every log associated w/ a session -->
|
||||
<fields>
|
||||
<!-- for example: channel variable "customer_account_number" will be the data source for the customer field in graylog2 -->
|
||||
<!--field name="customer" variable="customer_account_number"/-->
|
||||
</fields>
|
||||
</settings>
|
||||
</configuration>
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
<!-- Loggers (I'd load these first) -->
|
||||
<load module="mod_console"/>
|
||||
<!-- <load module="mod_graylog2"/> -->
|
||||
<load module="mod_logfile"/>
|
||||
<!-- <load module="mod_syslog"/> -->
|
||||
|
||||
|
@ -53,6 +54,7 @@
|
|||
<load module="mod_expr"/>
|
||||
<load module="mod_fifo"/>
|
||||
<load module="mod_hash"/>
|
||||
<!--<load module="mod_mongo"/> -->
|
||||
<load module="mod_voicemail"/>
|
||||
<!--<load module="mod_directory"/>-->
|
||||
<!--<load module="mod_distributor"/>-->
|
||||
|
|
|
@ -2,5 +2,18 @@
|
|||
<settings>
|
||||
<param name="use-vbr" value="1"/>
|
||||
<param name="complexity" value="10"/>
|
||||
|
||||
<!--
|
||||
maxaveragebitrate: the maximum average codec bitrate (values: 6000 to 510000 in bps) 0 is not considered
|
||||
maxplaybackrate: the maximum codec internal frequency (values: 8000, 12000, 16000, 24000, 48000 in Hz) 0 is not considered
|
||||
This will set the local encoder and instruct the remote encoder trough specific "fmtp" attibute in the SDP.
|
||||
|
||||
Example: if you receive "maxaveragebitrate=20000" from SDP and you have set "maxaveragebitrate=24000" in this configuration
|
||||
the lowest will prevail in this case "20000" is set on the encoder and the corresponding fmtp attribute will be set
|
||||
to instruct the remote encoder to do the same.
|
||||
-->
|
||||
<param name="maxaveragebitrate" value="0"/>
|
||||
<param name="maxplaybackrate" value="0"/>
|
||||
|
||||
</settings>
|
||||
</configuration>
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
<!-- Colorize the Console -->
|
||||
<param name="colorize-console" value="true"/>
|
||||
|
||||
<!--Include full timestamps in dialplan logs -->
|
||||
<param name="dialplan-timestamps" value="false"/>
|
||||
|
||||
<!-- Run the timer at 20ms by default and drop down as needed unless you set 1m-timer=true which was previous default -->
|
||||
<!-- <param name="1ms-timer" value="true"/> -->
|
||||
|
||||
|
|
|
@ -1558,6 +1558,7 @@ AC_CONFIG_FILES([Makefile
|
|||
src/mod/event_handlers/mod_format_cdr/Makefile
|
||||
src/mod/event_handlers/mod_json_cdr/Makefile
|
||||
src/mod/event_handlers/mod_radius_cdr/Makefile
|
||||
src/mod/event_handlers/mod_odbc_cdr/Makefile
|
||||
src/mod/event_handlers/mod_rayo/Makefile
|
||||
src/mod/event_handlers/mod_snmp/Makefile
|
||||
src/mod/event_handlers/mod_event_zmq/Makefile
|
||||
|
@ -1586,6 +1587,7 @@ AC_CONFIG_FILES([Makefile
|
|||
src/mod/say/mod_say_de/Makefile
|
||||
src/mod/say/mod_say_en/Makefile
|
||||
src/mod/say/mod_say_es/Makefile
|
||||
src/mod/say/mod_say_es_ar/Makefile
|
||||
src/mod/say/mod_say_fa/Makefile
|
||||
src/mod/say/mod_say_fr/Makefile
|
||||
src/mod/say/mod_say_he/Makefile
|
||||
|
|
|
@ -35,11 +35,13 @@ avoid_mods=(
|
|||
)
|
||||
avoid_mods_sid=(
|
||||
directories/mod_ldap
|
||||
formats/mod_shout
|
||||
languages/mod_java
|
||||
)
|
||||
avoid_mods_jessie=(
|
||||
directories/mod_ldap
|
||||
languages/mod_java
|
||||
formats/mod_shout
|
||||
)
|
||||
avoid_mods_wheezy=(
|
||||
languages/mod_java
|
||||
|
|
|
@ -333,9 +333,9 @@ Description: mod_opus
|
|||
Adds mod_opus.
|
||||
|
||||
Module: codecs/mod_sangoma_codec
|
||||
Build-Depends: libsngtc-dev
|
||||
Description: mod_sangoma_codec
|
||||
Adds mod_sangoma_codec.
|
||||
Build-Depends: libsngtc-dev
|
||||
|
||||
Module: codecs/mod_silk
|
||||
Description: mod_silk
|
||||
|
@ -500,6 +500,10 @@ Module: event_handlers/mod_json_cdr
|
|||
Description: mod_json_cdr
|
||||
Adds mod_json_cdr.
|
||||
|
||||
Module: event_handlers/mod_odbc_cdr
|
||||
Description: mod_odbc_cdr
|
||||
Adds mod_odbc_cdr.
|
||||
|
||||
Module: event_handlers/mod_radius_cdr
|
||||
Description: mod_radius_cdr
|
||||
Adds mod_radius_cdr.
|
||||
|
@ -630,6 +634,10 @@ Module: say/mod_say_es
|
|||
Description: mod_say_es
|
||||
Adds mod_say_es.
|
||||
|
||||
Module: say/mod_say_es_ar
|
||||
Description: mod_say_es_ar
|
||||
Adds mod_say_es_ar.
|
||||
|
||||
Module: say/mod_say_fa
|
||||
Description: mod_say_fa
|
||||
Adds mod_say_fa.
|
||||
|
|
|
@ -19,8 +19,7 @@ DESC=freeswitch
|
|||
NAME=freeswitch
|
||||
DAEMON=/usr/bin/freeswitch
|
||||
USER=freeswitch
|
||||
GROUP=freeswitch
|
||||
DAEMON_ARGS="-u $USER -g $GROUP -ncwait"
|
||||
DAEMON_ARGS="-u $USER -ncwait"
|
||||
CONFDIR=/etc/$NAME
|
||||
RUNDIR=/var/run/$NAME
|
||||
PIDFILE=$RUNDIR/$NAME.pid
|
||||
|
@ -35,13 +34,15 @@ WORKDIR=/var/lib/$NAME
|
|||
do_start() {
|
||||
if ! [ -f $CONFDIR/freeswitch.xml ]; then
|
||||
echo "$NAME is not configured so not starting.">&2
|
||||
echo "Please review /usr/share/doc/$NAME/README.Debian">&2
|
||||
echo "Please add configuration under /etc/freeswitch">&2
|
||||
echo "e.g. Install freeswitch-conf-vanilla, then:">&2
|
||||
echo "cp -a /usr/share/freeswitch/conf/vanilla /etc/freeswitch">&2
|
||||
return 3
|
||||
fi
|
||||
|
||||
# Directory in /var/run may disappear on reboot (e.g. when tmpfs used for /var/run).
|
||||
mkdir -p $RUNDIR
|
||||
chown -R $USER:$GROUP $RUNDIR
|
||||
chown -R $USER: $RUNDIR
|
||||
chmod -R ug=rwX,o= $RUNDIR
|
||||
|
||||
start-stop-daemon --start --quiet \
|
||||
|
|
|
@ -55,7 +55,6 @@ clean:
|
|||
dh $@
|
||||
|
||||
override_dh_auto_clean:
|
||||
dh_clean
|
||||
|
||||
.stamp-bootstrap:
|
||||
@$(call show_vars)
|
||||
|
|
|
@ -129,6 +129,7 @@ Source10: http://files.freeswitch.org/downloads/libs/libmemcached-0.32.tar.gz
|
|||
Source11: http://files.freeswitch.org/downloads/libs/json-c-0.9.tar.gz
|
||||
Source12: http://files.freeswitch.org/downloads/libs/opus-1.1-p2.tar.gz
|
||||
Source13: http://files.freeswitch.org/downloads/libs/v8-3.24.14.tar.bz2
|
||||
Source14: http://files.freeswitch.org/downloads/libs/mongo-c-driver-0.92.2.tar.gz
|
||||
Prefix: %{prefix}
|
||||
|
||||
|
||||
|
@ -482,6 +483,14 @@ is a "high-performance, distributed memory object caching system, generic in
|
|||
nature, but intended for use in speeding up dynamic web applications by
|
||||
alleviating database load."
|
||||
|
||||
%package application-mongo
|
||||
Summary: FreeSWITCH mod_mongo
|
||||
Group: System/Libraries
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
|
||||
%description application-mongo
|
||||
Provides FreeSWITCH mod_mongo, which implements an API interface to mongodb.
|
||||
|
||||
%package application-nibblebill
|
||||
Summary: FreeSWITCH mod_nibblebill
|
||||
Group: System/Libraries
|
||||
|
@ -1028,6 +1037,18 @@ BuildRequires: net-snmp-devel
|
|||
%description event-snmp
|
||||
SNMP stats reporter for the FreeSWITCH open source telephony platform
|
||||
|
||||
######################################################################################################################
|
||||
# FreeSWITCH Logger Modules
|
||||
######################################################################################################################
|
||||
|
||||
%package logger-graylog2
|
||||
Summary: GELF logger for Graylog2 and Logstash
|
||||
Group: System/Libraries
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
|
||||
%description logger-graylog2
|
||||
GELF logger for Graylog2 and Logstash
|
||||
|
||||
######################################################################################################################
|
||||
# FreeSWITCH Media Format Modules
|
||||
######################################################################################################################
|
||||
|
@ -1371,7 +1392,7 @@ APPLICATION_MODULES_DE+="applications/mod_esl"
|
|||
|
||||
APPLICATION_MODULES_FR="applications/mod_fifo applications/mod_fsk applications/mod_fsv applications/mod_hash \
|
||||
applications/mod_httapi applications/mod_http_cache applications/mod_lcr applications/mod_limit \
|
||||
applications/mod_memcache applications/mod_nibblebill applications/mod_redis applications/mod_rss"
|
||||
applications/mod_memcache applications/mod_mongo applications/mod_nibblebill applications/mod_redis applications/mod_rss"
|
||||
|
||||
APPLICATION_MODULES_SZ="applications/mod_sms applications/mod_snapshot applications/mod_snom applications/mod_soundtouch \
|
||||
applications/mod_spandsp applications/mod_spy applications/mod_stress \
|
||||
|
@ -1463,7 +1484,7 @@ LANGUAGES_MODULES="languages/mod_lua languages/mod_perl languages/mod_python "
|
|||
# Logging Modules
|
||||
#
|
||||
######################################################################################################################
|
||||
LOGGERS_MODULES="loggers/mod_console loggers/mod_logfile loggers/mod_syslog"
|
||||
LOGGERS_MODULES="loggers/mod_console loggers/mod_graylog2 loggers/mod_logfile loggers/mod_syslog"
|
||||
|
||||
######################################################################################################################
|
||||
#
|
||||
|
@ -1807,6 +1828,7 @@ fi
|
|||
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/fax.conf.xml
|
||||
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/fifo.conf.xml
|
||||
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/format_cdr.conf.xml
|
||||
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/graylog2.conf.xml
|
||||
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/hash.conf.xml
|
||||
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/httapi.conf.xml
|
||||
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/http_cache.conf.xml
|
||||
|
@ -1968,6 +1990,9 @@ fi
|
|||
%files application-memcache
|
||||
%{MODINSTDIR}/mod_memcache.so*
|
||||
|
||||
%files application-mongo
|
||||
%{MODINSTDIR}/mod_mongo.so*
|
||||
|
||||
%files application-nibblebill
|
||||
%{MODINSTDIR}/mod_nibblebill.so*
|
||||
|
||||
|
@ -2339,6 +2364,15 @@ fi
|
|||
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/lang/sv/vm/*.xml
|
||||
%{MODINSTDIR}/mod_say_sv.so*
|
||||
|
||||
######################################################################################################################
|
||||
#
|
||||
# Logger Modules
|
||||
#
|
||||
######################################################################################################################
|
||||
|
||||
%files logger-graylog2
|
||||
%{MODINSTDIR}/mod_graylog2.so*
|
||||
|
||||
######################################################################################################################
|
||||
#
|
||||
# Timer Modules
|
||||
|
@ -2371,6 +2405,8 @@ fi
|
|||
#
|
||||
######################################################################################################################
|
||||
%changelog
|
||||
* Tue Nov 04 2014 - crienzo@grasshopper.com
|
||||
- add mod_graylog2 and mod_mongo
|
||||
* Thu Sep 11 2014 - krice@freeswitch.org
|
||||
- add and fix mod_verto and mod_rtc
|
||||
* Fri Jul 20 2014 - krice@freeswitch.org
|
||||
|
|
|
@ -8,8 +8,14 @@ jsmin: jsmin.c
|
|||
verto-min.js: jsmin $(JSFILES)
|
||||
cat $(JSFILES) | ./jsmin > $@
|
||||
|
||||
verto-max.js: jsmin $(JSFILES)
|
||||
cat $(JSFILES) > $@
|
||||
|
||||
clean:
|
||||
rm -f verto-min.js jsmin *~
|
||||
rm -f verto-min.js verto-max.js jsmin *~
|
||||
|
||||
install-demo: all
|
||||
cp verto-min.js ../demo/js
|
||||
|
||||
install-maxdemo: all verto-max.js
|
||||
cp verto-max.js ../demo/js/verto-min.js
|
||||
|
|
|
@ -64,8 +64,9 @@
|
|||
var newLine = [];
|
||||
var index = 0;
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
if (index === 3) // Format of media starts from the fourth.
|
||||
newLine[index++] = payload; // Put target payload to the first.
|
||||
if (index === 3) { // Format of media starts from the fourth.
|
||||
newLine[index++] = payload; // Put target payload to the first.
|
||||
}
|
||||
if (elements[i] !== payload) newLine[index++] = elements[i];
|
||||
}
|
||||
return newLine.join(' ');
|
||||
|
@ -76,7 +77,7 @@
|
|||
useVideo: null,
|
||||
useStereo: false,
|
||||
userData: null,
|
||||
iceServers: false,
|
||||
iceServers: false,
|
||||
videoParams: {},
|
||||
audioParams: {},
|
||||
callbacks: {
|
||||
|
@ -84,8 +85,7 @@
|
|||
onICE: function() {},
|
||||
onOfferSDP: function() {}
|
||||
}
|
||||
},
|
||||
options);
|
||||
}, options);
|
||||
|
||||
this.mediaData = {
|
||||
SDP: null,
|
||||
|
@ -163,9 +163,9 @@
|
|||
function setCompat() {
|
||||
$.FSRTC.moz = !!navigator.mozGetUserMedia;
|
||||
//navigator.getUserMedia || (navigator.getUserMedia = navigator.mozGetUserMedia || navigator.webkitGetUserMedia || navigator.msGetUserMedia);
|
||||
if (!navigator.getUserMedia) {
|
||||
navigator.getUserMedia = navigator.mozGetUserMedia || navigator.webkitGetUserMedia || navigator.msGetUserMedia;
|
||||
}
|
||||
if (!navigator.getUserMedia) {
|
||||
navigator.getUserMedia = navigator.mozGetUserMedia || navigator.webkitGetUserMedia || navigator.msGetUserMedia;
|
||||
}
|
||||
}
|
||||
|
||||
function checkCompat() {
|
||||
|
@ -307,7 +307,7 @@
|
|||
return onChannelError(self, e);
|
||||
},
|
||||
constraints: self.constraints,
|
||||
iceServers: self.options.iceServers,
|
||||
iceServers: self.options.iceServers,
|
||||
offerSDP: {
|
||||
type: "offer",
|
||||
sdp: self.remoteSDP
|
||||
|
@ -324,9 +324,9 @@
|
|||
getUserMedia({
|
||||
constraints: {
|
||||
audio: {
|
||||
mandatory: this.options.audioParams,
|
||||
optional: []
|
||||
},
|
||||
mandatory: this.options.audioParams,
|
||||
optional: []
|
||||
},
|
||||
video: this.options.useVideo ? {
|
||||
mandatory: this.options.videoParams,
|
||||
optional: []
|
||||
|
@ -371,7 +371,7 @@
|
|||
return onChannelError(self, e);
|
||||
},
|
||||
constraints: self.constraints,
|
||||
iceServers: self.options.iceServers,
|
||||
iceServers: self.options.iceServers,
|
||||
});
|
||||
|
||||
onStreamSuccess(self);
|
||||
|
@ -384,9 +384,9 @@
|
|||
getUserMedia({
|
||||
constraints: {
|
||||
audio: {
|
||||
mandatory: this.options.audioParams,
|
||||
optional: []
|
||||
},
|
||||
mandatory: this.options.audioParams,
|
||||
optional: []
|
||||
},
|
||||
video: this.options.useVideo ? {
|
||||
mandatory: this.options.videoParams,
|
||||
optional: []
|
||||
|
@ -398,11 +398,11 @@
|
|||
});
|
||||
|
||||
/*
|
||||
navigator.getUserMedia({
|
||||
navigator.getUserMedia({
|
||||
video: this.options.useVideo,
|
||||
audio: true
|
||||
}, onSuccess, onError);
|
||||
*/
|
||||
}, onSuccess, onError);
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
|
@ -428,34 +428,34 @@
|
|||
credential: 'homeo'
|
||||
};
|
||||
|
||||
var iceServers = null;
|
||||
var iceServers = null;
|
||||
|
||||
if (options.iceServers) {
|
||||
var tmp = options.iceServers;;
|
||||
if (options.iceServers) {
|
||||
var tmp = options.iceServers;;
|
||||
|
||||
if (typeof(tmp) === "boolean") {
|
||||
tmp = null;
|
||||
}
|
||||
if (typeof(tmp) === "boolean") {
|
||||
tmp = null;
|
||||
}
|
||||
|
||||
if (tmp && typeof(tmp) !== "array") {
|
||||
console.warn("iceServers must be an array, reverting to default ice servers");
|
||||
tmp = null;
|
||||
}
|
||||
if (tmp && typeof(tmp) !== "array") {
|
||||
console.warn("iceServers must be an array, reverting to default ice servers");
|
||||
tmp = null;
|
||||
}
|
||||
|
||||
iceServers = {
|
||||
iceServers: tmp || [STUN]
|
||||
iceServers: tmp || [STUN]
|
||||
};
|
||||
|
||||
if (!moz && !tmp) {
|
||||
if (parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2]) >= 28) TURN = {
|
||||
if (parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2]) >= 28) TURN = {
|
||||
url: 'turn:turn.bistri.com:80',
|
||||
credential: 'homeo',
|
||||
username: 'homeo'
|
||||
};
|
||||
};
|
||||
|
||||
iceServers.iceServers = [STUN];
|
||||
iceServers.iceServers = [STUN];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var optional = {
|
||||
optional: []
|
||||
|
@ -488,30 +488,30 @@
|
|||
options.onICESDP(peer.localDescription);
|
||||
//x = 1;
|
||||
/*
|
||||
x = 1;
|
||||
peer.createOffer(function(sessionDescription) {
|
||||
sessionDescription.sdp = serializeSdp(sessionDescription.sdp);
|
||||
peer.setLocalDescription(sessionDescription);
|
||||
if (options.onICESDP) {
|
||||
options.onICESDP(sessionDescription);
|
||||
}
|
||||
}, onSdpError, constraints);
|
||||
*/
|
||||
x = 1;
|
||||
peer.createOffer(function(sessionDescription) {
|
||||
sessionDescription.sdp = serializeSdp(sessionDescription.sdp);
|
||||
peer.setLocalDescription(sessionDescription);
|
||||
if (options.onICESDP) {
|
||||
options.onICESDP(sessionDescription);
|
||||
}
|
||||
}, onSdpError, constraints);
|
||||
*/
|
||||
}
|
||||
} else {
|
||||
if (!x && options.onICESDP) {
|
||||
options.onICESDP(peer.localDescription);
|
||||
//x = 1;
|
||||
/*
|
||||
x = 1;
|
||||
peer.createAnswer(function(sessionDescription) {
|
||||
sessionDescription.sdp = serializeSdp(sessionDescription.sdp);
|
||||
peer.setLocalDescription(sessionDescription);
|
||||
if (options.onICESDP) {
|
||||
options.onICESDP(sessionDescription);
|
||||
}
|
||||
}, onSdpError, constraints);
|
||||
*/
|
||||
x = 1;
|
||||
peer.createAnswer(function(sessionDescription) {
|
||||
sessionDescription.sdp = serializeSdp(sessionDescription.sdp);
|
||||
peer.setLocalDescription(sessionDescription);
|
||||
if (options.onICESDP) {
|
||||
options.onICESDP(sessionDescription);
|
||||
}
|
||||
}, onSdpError, constraints);
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -730,8 +730,8 @@
|
|||
channel: channel,
|
||||
sendData: function(message) {
|
||||
if (channel) {
|
||||
channel.send(message);
|
||||
}
|
||||
channel.send(message);
|
||||
}
|
||||
},
|
||||
|
||||
stop: function() {
|
||||
|
@ -770,8 +770,8 @@
|
|||
//video.play();
|
||||
}
|
||||
if (options.onsuccess) {
|
||||
options.onsuccess(stream);
|
||||
}
|
||||
options.onsuccess(stream);
|
||||
}
|
||||
media = stream;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -73,10 +73,9 @@
|
|||
tag: null,
|
||||
videoParams: {},
|
||||
audioParams: {},
|
||||
iceServers: false,
|
||||
iceServers: false,
|
||||
ringSleep: 6000
|
||||
},
|
||||
options);
|
||||
}, options);
|
||||
|
||||
verto.sessid = $.cookie('verto_session_uuid') || generateGUID();
|
||||
$.cookie('verto_session_uuid', verto.sessid, {
|
||||
|
@ -84,9 +83,7 @@
|
|||
});
|
||||
|
||||
verto.dialogs = {};
|
||||
|
||||
verto.callbacks = callbacks || {};
|
||||
|
||||
verto.eventSUBS = {};
|
||||
|
||||
verto.rpcClient = new $.JsonRpcClient({
|
||||
|
@ -123,7 +120,6 @@
|
|||
|
||||
$.verto.prototype.iceServers = function(on) {
|
||||
var verto = this;
|
||||
|
||||
verto.options.iceServers = on;
|
||||
};
|
||||
|
||||
|
@ -172,7 +168,7 @@
|
|||
|
||||
$.verto.prototype.processReply = function(method, success, e) {
|
||||
var verto = this;
|
||||
var i;
|
||||
var i;
|
||||
|
||||
//console.log("Response: " + method, success, e);
|
||||
|
||||
|
@ -228,7 +224,7 @@
|
|||
}
|
||||
|
||||
var SERNO = 1;
|
||||
|
||||
|
||||
function do_subscribe(verto, channel, subChannels, sparams) {
|
||||
var params = sparams || {};
|
||||
|
||||
|
@ -298,7 +294,7 @@
|
|||
|
||||
$.verto.prototype.unsubscribe = function(handle) {
|
||||
var verto = this;
|
||||
var i;
|
||||
var i;
|
||||
|
||||
if (!handle) {
|
||||
for (i in verto.eventSUBS) {
|
||||
|
@ -309,7 +305,7 @@
|
|||
} else {
|
||||
var unsubChannels = {};
|
||||
var sendChannels = [];
|
||||
var channel;
|
||||
var channel;
|
||||
|
||||
if (typeof(handle) == "string") {
|
||||
delete verto.eventSUBS[handle];
|
||||
|
@ -368,13 +364,13 @@
|
|||
$.verto.prototype.purge = function(callID) {
|
||||
var verto = this;
|
||||
var x = 0;
|
||||
var i;
|
||||
var i;
|
||||
|
||||
for (i in verto.dialogs) {
|
||||
if (!x) {
|
||||
console.log("purging dialogs");
|
||||
}
|
||||
x++;
|
||||
x++;
|
||||
verto.dialogs[i].setState($.verto.enum.state.purge);
|
||||
}
|
||||
|
||||
|
@ -423,10 +419,10 @@
|
|||
$.verto.prototype.handleMessage = function(data) {
|
||||
var verto = this;
|
||||
|
||||
if (!(data && data.method)) {
|
||||
console.error("Invalid Data", data);
|
||||
return;
|
||||
}
|
||||
if (!(data && data.method)) {
|
||||
console.error("Invalid Data", data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.params.callID) {
|
||||
var dialog = verto.dialogs[data.params.callID];
|
||||
|
@ -467,10 +463,10 @@
|
|||
data.params.useStereo = true;
|
||||
}
|
||||
|
||||
dialog = new $.verto.dialog($.verto.enum.direction.inbound, verto, data.params);
|
||||
dialog = new $.verto.dialog($.verto.enum.direction.inbound, verto, data.params);
|
||||
dialog.setState($.verto.enum.state.recovering);
|
||||
|
||||
break;
|
||||
break;
|
||||
case 'verto.invite':
|
||||
|
||||
if (data.params.sdp && data.params.sdp.indexOf("m=video") > 0) {
|
||||
|
@ -510,10 +506,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
if (!list && key && key === verto.sessid) {
|
||||
if (verto.callbacks.onMessage) {
|
||||
verto.callbacks.onMessage(verto, null, $.verto.enum.message.pvtEvent, data.params);
|
||||
}
|
||||
if (!list && key && key === verto.sessid) {
|
||||
if (verto.callbacks.onMessage) {
|
||||
verto.callbacks.onMessage(verto, null, $.verto.enum.message.pvtEvent, data.params);
|
||||
}
|
||||
} else if (!list && key && verto.dialogs[key]) {
|
||||
verto.dialogs[key].sendMessage($.verto.enum.message.pvtEvent, data.params);
|
||||
} else if (!list) {
|
||||
|
@ -944,21 +940,21 @@
|
|||
la.verto.unsubscribe(binding);
|
||||
};
|
||||
|
||||
la.sendCommand = function(cmd, obj) {
|
||||
la.sendCommand = function(cmd, obj) {
|
||||
var self = la;
|
||||
self.broadcast(self.context, {
|
||||
liveArray: {
|
||||
self.broadcast(self.context, {
|
||||
liveArray: {
|
||||
command: cmd,
|
||||
context: self.context,
|
||||
name: self.name,
|
||||
obj: obj
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
la.bootstrap = function(obj) {
|
||||
var self = la;
|
||||
la.sendCommand("bootstrap", obj);
|
||||
la.sendCommand("bootstrap", obj);
|
||||
//self.heartbeat();
|
||||
};
|
||||
|
||||
|
@ -1128,7 +1124,7 @@
|
|||
} else {
|
||||
obj.errs = 0;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
la.onChange(la, {
|
||||
|
@ -1138,211 +1134,205 @@
|
|||
};
|
||||
|
||||
var CONFMAN_SERNO = 1;
|
||||
|
||||
|
||||
$.verto.confMan = function(verto, params) {
|
||||
var confMan = this;
|
||||
conf
|
||||
var confMan = this;
|
||||
conf
|
||||
confMan.params = $.extend({
|
||||
tableID: null,
|
||||
statusID: null,
|
||||
mainModID: null,
|
||||
dialog: null,
|
||||
hasVid: false,
|
||||
laData: null,
|
||||
onBroadcast: null,
|
||||
onLaChange: null,
|
||||
onLaRow: null
|
||||
},
|
||||
params);
|
||||
tableID: null,
|
||||
statusID: null,
|
||||
mainModID: null,
|
||||
dialog: null,
|
||||
hasVid: false,
|
||||
laData: null,
|
||||
onBroadcast: null,
|
||||
onLaChange: null,
|
||||
onLaRow: null
|
||||
}, params);
|
||||
|
||||
confMan.verto = verto;
|
||||
confMan.serno = CONFMAN_SERNO++;
|
||||
confMan.verto = verto;
|
||||
confMan.serno = CONFMAN_SERNO++;
|
||||
|
||||
function genMainMod(jq) {
|
||||
var play_id = "play_" + confMan.serno;
|
||||
var stop_id = "stop_" + confMan.serno;
|
||||
var recording_id = "recording_" + confMan.serno;
|
||||
var rec_stop_id = "recording_stop" + confMan.serno;
|
||||
var div_id = "confman_" + confMan.serno;
|
||||
function genMainMod(jq) {
|
||||
var play_id = "play_" + confMan.serno;
|
||||
var stop_id = "stop_" + confMan.serno;
|
||||
var recording_id = "recording_" + confMan.serno;
|
||||
var rec_stop_id = "recording_stop" + confMan.serno;
|
||||
var div_id = "confman_" + confMan.serno;
|
||||
|
||||
var html = "<div id='" + div_id + "'><br>" +
|
||||
"<button class='ctlbtn' id='" + play_id + "'>Play</button>" +
|
||||
"<button class='ctlbtn' id='" + stop_id + "'>Stop</button>" +
|
||||
"<button class='ctlbtn' id='" + recording_id + "'>Record</button>" +
|
||||
"<button class='ctlbtn' id='" + rec_stop_id + "'>Record Stop</button>"
|
||||
var html = "<div id='" + div_id + "'><br>" +
|
||||
"<button class='ctlbtn' id='" + play_id + "'>Play</button>" +
|
||||
"<button class='ctlbtn' id='" + stop_id + "'>Stop</button>" +
|
||||
"<button class='ctlbtn' id='" + recording_id + "'>Record</button>" +
|
||||
"<button class='ctlbtn' id='" + rec_stop_id + "'>Record Stop</button>"
|
||||
|
||||
+ "<br><br></div>";
|
||||
+ "<br><br></div>";
|
||||
|
||||
jq.html(html);
|
||||
jq.html(html);
|
||||
|
||||
$("#" + play_id).click(function() {
|
||||
var file = prompt("Please enter file name", "");
|
||||
confMan.modCommand("play", null, file);
|
||||
});
|
||||
$("#" + play_id).click(function() {
|
||||
var file = prompt("Please enter file name", "");
|
||||
confMan.modCommand("play", null, file);
|
||||
});
|
||||
|
||||
$("#" + stop_id).click(function() {
|
||||
confMan.modCommand("stop", null, "all");
|
||||
});
|
||||
$("#" + stop_id).click(function() {
|
||||
confMan.modCommand("stop", null, "all");
|
||||
});
|
||||
|
||||
$("#" + recording_id).click(function() {
|
||||
var file = prompt("Please enter file name", "");
|
||||
confMan.modCommand("recording", null, ["start", file]);
|
||||
});
|
||||
$("#" + recording_id).click(function() {
|
||||
var file = prompt("Please enter file name", "");
|
||||
confMan.modCommand("recording", null, ["start", file]);
|
||||
});
|
||||
|
||||
$("#" + rec_stop_id).click(function() {
|
||||
confMan.modCommand("recording", null, ["stop", "all"]);
|
||||
});
|
||||
$("#" + rec_stop_id).click(function() {
|
||||
confMan.modCommand("recording", null, ["stop", "all"]);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function genControls(jq, rowid) {
|
||||
var x = parseInt(rowid);
|
||||
var kick_id = "kick_" + x;
|
||||
var tmute_id = "tmute_" + x;
|
||||
var box_id = "box_" + x;
|
||||
var volup_id = "volume_in_up" + x;
|
||||
var voldn_id = "volume_in_dn" + x;
|
||||
var transfer_id = "transfer" + x;
|
||||
|
||||
|
||||
var html = "<div id='" + box_id + "'>" +
|
||||
"<button class='ctlbtn' id='" + kick_id + "'>Kick</button>" +
|
||||
"<button class='ctlbtn' id='" + tmute_id + "'>Mute</button>" +
|
||||
"<button class='ctlbtn' id='" + voldn_id + "'>Vol -</button>" +
|
||||
"<button class='ctlbtn' id='" + volup_id + "'>Vol +</button>" +
|
||||
"<button class='ctlbtn' id='" + transfer_id + "'>Transfer</button>" +
|
||||
"</div>"
|
||||
;
|
||||
|
||||
jq.html(html);
|
||||
|
||||
if (!jq.data("mouse")) {
|
||||
$("#" + box_id).hide();
|
||||
}
|
||||
|
||||
jq.mouseover(function(e) {
|
||||
jq.data({"mouse": true});
|
||||
$("#" + box_id).show();
|
||||
});
|
||||
|
||||
jq.mouseout(function(e) {
|
||||
jq.data({"mouse": false});
|
||||
$("#" + box_id).hide();
|
||||
});
|
||||
|
||||
$("#" + transfer_id).click(function() {
|
||||
var xten = prompt("Enter Extension");
|
||||
confMan.modCommand("transfer", x, xten);
|
||||
});
|
||||
|
||||
$("#" + kick_id).click(function() {
|
||||
confMan.modCommand("kick", x);
|
||||
});
|
||||
|
||||
$("#" + tmute_id).click(function() {
|
||||
confMan.modCommand("tmute", x);
|
||||
});
|
||||
|
||||
$("#" + volup_id).click(function() {
|
||||
confMan.modCommand("volume_in", x, "up");
|
||||
});
|
||||
|
||||
$("#" + voldn_id).click(function() {
|
||||
confMan.modCommand("volume_in", x, "down");
|
||||
});
|
||||
|
||||
return html;
|
||||
}
|
||||
function genControls(jq, rowid) {
|
||||
var x = parseInt(rowid);
|
||||
var kick_id = "kick_" + x;
|
||||
var tmute_id = "tmute_" + x;
|
||||
var box_id = "box_" + x;
|
||||
var volup_id = "volume_in_up" + x;
|
||||
var voldn_id = "volume_in_dn" + x;
|
||||
var transfer_id = "transfer" + x;
|
||||
|
||||
|
||||
var html = "<div id='" + box_id + "'>" +
|
||||
"<button class='ctlbtn' id='" + kick_id + "'>Kick</button>" +
|
||||
"<button class='ctlbtn' id='" + tmute_id + "'>Mute</button>" +
|
||||
"<button class='ctlbtn' id='" + voldn_id + "'>Vol -</button>" +
|
||||
"<button class='ctlbtn' id='" + volup_id + "'>Vol +</button>" +
|
||||
"<button class='ctlbtn' id='" + transfer_id + "'>Transfer</button>" +
|
||||
"</div>"
|
||||
;
|
||||
|
||||
jq.html(html);
|
||||
|
||||
if (!jq.data("mouse")) {
|
||||
$("#" + box_id).hide();
|
||||
}
|
||||
|
||||
jq.mouseover(function(e) {
|
||||
jq.data({"mouse": true});
|
||||
$("#" + box_id).show();
|
||||
});
|
||||
|
||||
jq.mouseout(function(e) {
|
||||
jq.data({"mouse": false});
|
||||
$("#" + box_id).hide();
|
||||
});
|
||||
|
||||
$("#" + transfer_id).click(function() {
|
||||
var xten = prompt("Enter Extension");
|
||||
confMan.modCommand("transfer", x, xten);
|
||||
});
|
||||
|
||||
$("#" + kick_id).click(function() {
|
||||
confMan.modCommand("kick", x);
|
||||
});
|
||||
|
||||
$("#" + tmute_id).click(function() {
|
||||
confMan.modCommand("tmute", x);
|
||||
});
|
||||
|
||||
$("#" + volup_id).click(function() {
|
||||
confMan.modCommand("volume_in", x, "up");
|
||||
});
|
||||
|
||||
$("#" + voldn_id).click(function() {
|
||||
confMan.modCommand("volume_in", x, "down");
|
||||
});
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
var atitle = "";
|
||||
var awidth = 0;
|
||||
|
||||
var atitle = "";
|
||||
var awidth = 0;
|
||||
|
||||
//$(".jsDataTable").width(confMan.params.hasVid ? "900px" : "800px");
|
||||
|
||||
if (confMan.params.laData.role === "moderator") {
|
||||
atitle = "Action";
|
||||
awidth = 200;
|
||||
|
||||
if (confMan.params.mainModID) {
|
||||
genMainMod($(confMan.params.mainModID));
|
||||
$(confMan.params.displayID).html("Moderator Controls Ready<br><br>")
|
||||
} else {
|
||||
$(confMan.params.mainModID).html("");
|
||||
}
|
||||
|
||||
verto.subscribe(confMan.params.laData.modChannel, {
|
||||
handler: function(v, e) {
|
||||
console.error("MODDATA:", e.data);
|
||||
if (confMan.params.onBroadcast) {
|
||||
confMan.params.onBroadcast(verto, confMan, e.data);
|
||||
}
|
||||
if (!confMan.destroyed && confMan.params.displayID) {
|
||||
$(confMan.params.displayID).html(e.data.response + "<br><br>");
|
||||
if (confMan.lastTimeout) {
|
||||
clearTimeout(confMan.lastTimeout);
|
||||
confMan.lastTimeout = 0;
|
||||
}
|
||||
confMan.lastTimeout = setTimeout(function() { $(confMan.params.displayID).html(confMan.destroyed ? "" : "Moderator Controls Ready<br><br>")}, 4000);
|
||||
}
|
||||
if (confMan.params.laData.role === "moderator") {
|
||||
atitle = "Action";
|
||||
awidth = 200;
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
var row_callback = null;
|
||||
if (confMan.params.mainModID) {
|
||||
genMainMod($(confMan.params.mainModID));
|
||||
$(confMan.params.displayID).html("Moderator Controls Ready<br><br>")
|
||||
} else {
|
||||
$(confMan.params.mainModID).html("");
|
||||
}
|
||||
|
||||
if (confMan.params.laData.role === "moderator") {
|
||||
row_callback = function(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
|
||||
if (!aData[5]) {
|
||||
var $row = $('td:eq(5)', nRow);
|
||||
genControls($row, aData);
|
||||
|
||||
if (confMan.params.onLaRow) {
|
||||
confMan.params.onLaRow(verto, confMan, $row, aData);
|
||||
}
|
||||
verto.subscribe(confMan.params.laData.modChannel, {
|
||||
handler: function(v, e) {
|
||||
console.error("MODDATA:", e.data);
|
||||
if (confMan.params.onBroadcast) {
|
||||
confMan.params.onBroadcast(verto, confMan, e.data);
|
||||
}
|
||||
if (!confMan.destroyed && confMan.params.displayID) {
|
||||
$(confMan.params.displayID).html(e.data.response + "<br><br>");
|
||||
if (confMan.lastTimeout) {
|
||||
clearTimeout(confMan.lastTimeout);
|
||||
confMan.lastTimeout = 0;
|
||||
}
|
||||
confMan.lastTimeout = setTimeout(function() { $(confMan.params.displayID).html(confMan.destroyed ? "" : "Moderator Controls Ready<br><br>")}, 4000);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var row_callback = null;
|
||||
|
||||
if (confMan.params.laData.role === "moderator") {
|
||||
row_callback = function(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
|
||||
if (!aData[5]) {
|
||||
var $row = $('td:eq(5)', nRow);
|
||||
genControls($row, aData);
|
||||
|
||||
if (confMan.params.onLaRow) {
|
||||
confMan.params.onLaRow(verto, confMan, $row, aData);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
confMan.lt = new $.verto.liveTable(verto, confMan.params.laData.laChannel, confMan.params.laData.laName, $(confMan.params.tableID), {
|
||||
subParams: {
|
||||
callID: confMan.params.dialog ? confMan.params.dialog.callID : null
|
||||
},
|
||||
|
||||
|
||||
|
||||
"onChange": function(obj, args) {
|
||||
$(confMan.params.statusID).text("Conference Members: " + " (" + obj.arrayLen() + " Total)");
|
||||
if (confMan.params.onLaChange) {
|
||||
confMan.params.onLaChange(verto, confMan, $.verto.enum.confEvent.laChange, obj, args);
|
||||
}
|
||||
if (confMan.params.onLaChange) {
|
||||
confMan.params.onLaChange(verto, confMan, $.verto.enum.confEvent.laChange, obj, args);
|
||||
}
|
||||
},
|
||||
|
||||
"aaData": [],
|
||||
"aoColumns": [{
|
||||
"sTitle": "ID"
|
||||
},
|
||||
{
|
||||
"sTitle": "Number"
|
||||
},
|
||||
{
|
||||
"sTitle": "Name"
|
||||
},
|
||||
{
|
||||
"sTitle": "Codec"
|
||||
},
|
||||
{
|
||||
"sTitle": "Status",
|
||||
"sWidth": confMan.params.hasVid ? "300px" : "150px"
|
||||
},
|
||||
{
|
||||
"sTitle": atitle,
|
||||
"sWidth": awidth,
|
||||
|
||||
}],
|
||||
"aoColumns": [
|
||||
{
|
||||
"sTitle": "ID"
|
||||
},
|
||||
{
|
||||
"sTitle": "Number"
|
||||
},
|
||||
{
|
||||
"sTitle": "Name"
|
||||
},
|
||||
{
|
||||
"sTitle": "Codec"
|
||||
},
|
||||
{
|
||||
"sTitle": "Status",
|
||||
"sWidth": confMan.params.hasVid ? "300px" : "150px"
|
||||
},
|
||||
{
|
||||
"sTitle": atitle,
|
||||
"sWidth": awidth,
|
||||
}
|
||||
],
|
||||
"bAutoWidth": true,
|
||||
"bDestroy": true,
|
||||
"bSort": false,
|
||||
|
@ -1356,41 +1346,41 @@
|
|||
"sEmptyTable": "The Conference is Empty....."
|
||||
},
|
||||
|
||||
"fnRowCallback": row_callback
|
||||
"fnRowCallback": row_callback
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
$.verto.confMan.prototype.modCommand = function(cmd, id, value) {
|
||||
var confMan = this;
|
||||
|
||||
confMan.verto.sendMethod("verto.broadcast", {
|
||||
"eventChannel": confMan.params.laData.modChannel,
|
||||
"data": {
|
||||
"application": "conf-control",
|
||||
"command": cmd,
|
||||
"id": id,
|
||||
"value": value
|
||||
}
|
||||
});
|
||||
var confMan = this;
|
||||
|
||||
confMan.verto.sendMethod("verto.broadcast", {
|
||||
"eventChannel": confMan.params.laData.modChannel,
|
||||
"data": {
|
||||
"application": "conf-control",
|
||||
"command": cmd,
|
||||
"id": id,
|
||||
"value": value
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$.verto.confMan.prototype.destroy = function() {
|
||||
var confMan = this;
|
||||
var confMan = this;
|
||||
|
||||
confMan.destroyed = true;
|
||||
confMan.destroyed = true;
|
||||
|
||||
if (confMan.lt) {
|
||||
confMan.lt.destroy();
|
||||
}
|
||||
if (confMan.lt) {
|
||||
confMan.lt.destroy();
|
||||
}
|
||||
|
||||
if (confMan.params.laData.modChannel) {
|
||||
confMan.verto.unsubscribe(confMan.params.laData.modChannel);
|
||||
}
|
||||
if (confMan.params.laData.modChannel) {
|
||||
confMan.verto.unsubscribe(confMan.params.laData.modChannel);
|
||||
}
|
||||
|
||||
if (confMan.params.mainModID) {
|
||||
$(confMan.params.mainModID).html("");
|
||||
}
|
||||
if (confMan.params.mainModID) {
|
||||
$(confMan.params.mainModID).html("");
|
||||
}
|
||||
}
|
||||
|
||||
$.verto.dialog = function(direction, verto, params) {
|
||||
|
@ -1400,9 +1390,8 @@
|
|||
useVideo: verto.options.useVideo,
|
||||
useStereo: verto.options.useStereo,
|
||||
tag: verto.options.tag,
|
||||
login: verto.options.login
|
||||
},
|
||||
params);
|
||||
login: verto.options.login
|
||||
}, params);
|
||||
|
||||
dialog.verto = verto;
|
||||
dialog.direction = direction;
|
||||
|
@ -1431,13 +1420,13 @@
|
|||
var RTCcallbacks = {};
|
||||
|
||||
if (dialog.direction == $.verto.enum.direction.inbound) {
|
||||
if (dialog.params.display_direction === "outbound") {
|
||||
dialog.params.remote_caller_id_name = dialog.params.caller_id_name;
|
||||
dialog.params.remote_caller_id_number = dialog.params.caller_id_number;
|
||||
} else {
|
||||
dialog.params.remote_caller_id_name = dialog.params.callee_id_name;
|
||||
dialog.params.remote_caller_id_number = dialog.params.callee_id_number;
|
||||
}
|
||||
if (dialog.params.display_direction === "outbound") {
|
||||
dialog.params.remote_caller_id_name = dialog.params.caller_id_name;
|
||||
dialog.params.remote_caller_id_number = dialog.params.caller_id_number;
|
||||
} else {
|
||||
dialog.params.remote_caller_id_name = dialog.params.callee_id_name;
|
||||
dialog.params.remote_caller_id_number = dialog.params.callee_id_number;
|
||||
}
|
||||
|
||||
if (!dialog.params.remote_caller_id_name) {
|
||||
dialog.params.remote_caller_id_name = "Nobody";
|
||||
|
@ -1469,14 +1458,13 @@
|
|||
dialog.sendMethod("verto.invite", {
|
||||
sdp: rtc.mediaData.SDP
|
||||
});
|
||||
} else { //answer
|
||||
} else { //answer
|
||||
dialog.setState($.verto.enum.state.answering);
|
||||
|
||||
dialog.sendMethod(dialog.attach ? "verto.attach" : "verto.answer", {
|
||||
sdp: dialog.rtc.mediaData.SDP
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
RTCcallbacks.onICE = function(rtc) {
|
||||
|
@ -1485,7 +1473,6 @@
|
|||
console.log("offer", rtc.mediaData.candidate);
|
||||
return;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
RTCcallbacks.onError = function(e) {
|
||||
|
@ -1500,7 +1487,7 @@
|
|||
useStereo: dialog.params.useStereo,
|
||||
videoParams: verto.options.videoParams,
|
||||
audioParams: verto.options.audioParams,
|
||||
iceServers: verto.options.iceServers
|
||||
iceServers: verto.options.iceServers
|
||||
});
|
||||
|
||||
dialog.rtc.verto = dialog.verto;
|
||||
|
@ -1570,14 +1557,14 @@
|
|||
|
||||
dialog.lastState = dialog.state;
|
||||
dialog.state = state;
|
||||
|
||||
if (!dialog.causeCode) {
|
||||
dialog.causeCode = 16;
|
||||
}
|
||||
|
||||
if (!dialog.cause) {
|
||||
dialog.cause = "NORMAL CLEARING";
|
||||
}
|
||||
if (!dialog.causeCode) {
|
||||
dialog.causeCode = 16;
|
||||
}
|
||||
|
||||
if (!dialog.cause) {
|
||||
dialog.cause = "NORMAL CLEARING";
|
||||
}
|
||||
|
||||
if (dialog.callbacks.onDialogState) {
|
||||
dialog.callbacks.onDialogState(this);
|
||||
|
@ -1585,12 +1572,12 @@
|
|||
|
||||
switch (dialog.state) {
|
||||
case $.verto.enum.state.trying:
|
||||
setTimeout(function() {
|
||||
setTimeout(function() {
|
||||
if (dialog.state == $.verto.enum.state.trying) {
|
||||
dialog.setState($.verto.enum.state.hangup);
|
||||
dialog.setState($.verto.enum.state.hangup);
|
||||
}
|
||||
}, 30000);
|
||||
break;
|
||||
break;
|
||||
case $.verto.enum.state.purge:
|
||||
dialog.setState($.verto.enum.state.destroy);
|
||||
break;
|
||||
|
@ -1603,7 +1590,7 @@
|
|||
dialog.setState($.verto.enum.state.destroy);
|
||||
break;
|
||||
case $.verto.enum.state.destroy:
|
||||
delete dialog.verto.dialogs[dialog.callID];
|
||||
delete dialog.verto.dialogs[dialog.callID];
|
||||
dialog.rtc.stop();
|
||||
break;
|
||||
}
|
||||
|
@ -1664,15 +1651,15 @@
|
|||
$.verto.dialog.prototype.hangup = function(params) {
|
||||
var dialog = this;
|
||||
|
||||
if (params) {
|
||||
if (params.causeCode) {
|
||||
dialog.causeCode = params.causeCode;
|
||||
}
|
||||
|
||||
if (params.cause) {
|
||||
dialog.cause = params.cause;
|
||||
}
|
||||
}
|
||||
if (params) {
|
||||
if (params.causeCode) {
|
||||
dialog.causeCode = params.causeCode;
|
||||
}
|
||||
|
||||
if (params.cause) {
|
||||
dialog.cause = params.cause;
|
||||
}
|
||||
}
|
||||
|
||||
if (dialog.state.val > $.verto.enum.state.new.val && dialog.state.val < $.verto.enum.state.hangup.val) {
|
||||
dialog.setState($.verto.enum.state.hangup);
|
||||
|
@ -1784,7 +1771,7 @@
|
|||
var dialog = this;
|
||||
var err = 0;
|
||||
|
||||
msg.from = dialog.params.login;
|
||||
msg.from = dialog.params.login;
|
||||
|
||||
if (!msg.to) {
|
||||
console.error("Missing To");
|
||||
|
@ -1815,8 +1802,8 @@
|
|||
if (params.useVideo) {
|
||||
dialog.useVideo(true);
|
||||
}
|
||||
dialog.params.callee_id_name = params.callee_id_name;
|
||||
dialog.params.callee_id_number = params.callee_id_number;
|
||||
dialog.params.callee_id_name = params.callee_id_name;
|
||||
dialog.params.callee_id_number = params.callee_id_number;
|
||||
}
|
||||
dialog.rtc.createAnswer(dialog.params.sdp);
|
||||
dialog.answered = true;
|
||||
|
@ -1826,7 +1813,7 @@
|
|||
$.verto.dialog.prototype.handleAnswer = function(params) {
|
||||
var dialog = this;
|
||||
|
||||
dialog.gotAnswer = true;
|
||||
dialog.gotAnswer = true;
|
||||
|
||||
if (dialog.state.val >= $.verto.enum.state.active.val) {
|
||||
return;
|
||||
|
@ -1835,20 +1822,19 @@
|
|||
if (dialog.state.val >= $.verto.enum.state.early.val) {
|
||||
dialog.setState($.verto.enum.state.active);
|
||||
} else {
|
||||
if (dialog.gotEarly) {
|
||||
console.log("Dialog " + dialog.callID + "Got answer while still establishing early media, delaying...");
|
||||
} else {
|
||||
console.log("Dialog " + dialog.callID + "Answering Channel");
|
||||
dialog.rtc.answer(params.sdp, function() {
|
||||
if (dialog.gotEarly) {
|
||||
console.log("Dialog " + dialog.callID + "Got answer while still establishing early media, delaying...");
|
||||
} else {
|
||||
console.log("Dialog " + dialog.callID + "Answering Channel");
|
||||
dialog.rtc.answer(params.sdp, function() {
|
||||
dialog.setState($.verto.enum.state.active);
|
||||
},
|
||||
function(e) {
|
||||
console.error(e);
|
||||
dialog.hangup();
|
||||
});
|
||||
console.log("Dialog " + dialog.callID + "ANSWER SDP", params.sdp);
|
||||
}, function(e) {
|
||||
console.error(e);
|
||||
dialog.hangup();
|
||||
});
|
||||
console.log("Dialog " + dialog.callID + "ANSWER SDP", params.sdp);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.verto.dialog.prototype.cidString = function(enc) {
|
||||
|
@ -1891,18 +1877,17 @@
|
|||
return;
|
||||
}
|
||||
|
||||
dialog.gotEarly = true;
|
||||
|
||||
dialog.rtc.answer(params.sdp, function() {
|
||||
console.log("Dialog " + dialog.callID + "Establishing early media");
|
||||
dialog.setState($.verto.enum.state.early);
|
||||
dialog.gotEarly = true;
|
||||
|
||||
if (dialog.gotAnswer) {
|
||||
console.log("Dialog " + dialog.callID + "Answering Channel");
|
||||
dialog.setState($.verto.enum.state.active);
|
||||
}
|
||||
},
|
||||
function(e) {
|
||||
dialog.rtc.answer(params.sdp, function() {
|
||||
console.log("Dialog " + dialog.callID + "Establishing early media");
|
||||
dialog.setState($.verto.enum.state.early);
|
||||
|
||||
if (dialog.gotAnswer) {
|
||||
console.log("Dialog " + dialog.callID + "Answering Channel");
|
||||
dialog.setState($.verto.enum.state.active);
|
||||
}
|
||||
}, function(e) {
|
||||
console.error(e);
|
||||
dialog.hangup();
|
||||
});
|
||||
|
@ -1926,7 +1911,7 @@
|
|||
$.verto.enum.states = Object.freeze({
|
||||
new: {
|
||||
requesting: 1,
|
||||
recovering: 1,
|
||||
recovering: 1,
|
||||
ringing: 1,
|
||||
destroy: 1,
|
||||
answering: 1
|
||||
|
@ -1953,8 +1938,8 @@
|
|||
hangup: 1
|
||||
},
|
||||
active: {
|
||||
answering: 1,
|
||||
requesting: 1,
|
||||
answering: 1,
|
||||
requesting: 1,
|
||||
hangup: 1,
|
||||
held: 1
|
||||
},
|
||||
|
|
|
@ -566,7 +566,7 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session)
|
|||
}
|
||||
|
||||
if (!uuid_found) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Device [%d:%d] is no longer attached to %s. Nothing to do.\n", span_id, chan_id, name);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Device [%d:%d] is no longer attached to %s\n", span_id, chan_id, name);
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
@ -3830,6 +3830,7 @@ static switch_status_t load_config(void)
|
|||
const char *tonegroup = NULL;
|
||||
char *digit_timeout = NULL;
|
||||
char *dial_timeout = NULL;
|
||||
char *release_guard_time_ms = NULL;
|
||||
char *max_digits = NULL;
|
||||
char *dial_regex = NULL;
|
||||
char *hold_music = NULL;
|
||||
|
@ -3839,7 +3840,7 @@ static switch_status_t load_config(void)
|
|||
char *answer_supervision = str_false;
|
||||
char *immediate_ringback = str_false;
|
||||
char *ringback_file = str_empty;
|
||||
uint32_t span_id = 0, to = 0, max = 0, dial_timeout_int = 0;
|
||||
uint32_t span_id = 0, to = 0, max = 0, dial_timeout_int = 0, release_guard_time_ms_int = 0;
|
||||
ftdm_span_t *span = NULL;
|
||||
analog_option_t analog_options = ANALOG_OPTION_NONE;
|
||||
|
||||
|
@ -3853,6 +3854,8 @@ static switch_status_t load_config(void)
|
|||
digit_timeout = val;
|
||||
} else if (!strcasecmp(var, "dial-timeout")) {
|
||||
dial_timeout = val;
|
||||
} else if (!strcasecmp(var, "release-guard-time-ms")) {
|
||||
release_guard_time_ms = val;
|
||||
} else if (!strcasecmp(var, "context")) {
|
||||
context = val;
|
||||
} else if (!strcasecmp(var, "dialplan")) {
|
||||
|
@ -3893,6 +3896,10 @@ static switch_status_t load_config(void)
|
|||
dial_timeout_int = atoi(dial_timeout);
|
||||
}
|
||||
|
||||
if (release_guard_time_ms) {
|
||||
release_guard_time_ms_int = atoi(release_guard_time_ms);
|
||||
}
|
||||
|
||||
if (max_digits) {
|
||||
max = atoi(max_digits);
|
||||
}
|
||||
|
@ -3928,6 +3935,7 @@ static switch_status_t load_config(void)
|
|||
"ringback_file", ringback_file,
|
||||
"digit_timeout", &to,
|
||||
"dial_timeout", &dial_timeout_int,
|
||||
"release_guard_time_ms", &release_guard_time_ms_int,
|
||||
"max_dialstr", &max,
|
||||
FTDM_TAG_END) != FTDM_SUCCESS) {
|
||||
LOAD_ERROR("Error starting FreeTDM span %d\n", span_id);
|
||||
|
@ -5246,6 +5254,98 @@ end:
|
|||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#define CASINTS(cas) ((cas) & (1 << 3)) ? 1 : 0, \
|
||||
((cas) & (1 << 2)) ? 1 : 0, \
|
||||
((cas) & (1 << 1)) ? 1 : 0, \
|
||||
((cas) & (1 << 0)) ? 1 : 0
|
||||
FTDM_CLI_DECLARE(ftdm_cmd_cas)
|
||||
{
|
||||
uint32_t chan_id = 0;
|
||||
switch_bool_t do_read = SWITCH_FALSE;
|
||||
ftdm_channel_t *chan;
|
||||
ftdm_iterator_t *iter = NULL;
|
||||
ftdm_iterator_t *curr = NULL;
|
||||
ftdm_span_t *span = NULL;
|
||||
const char *write_bits_str = "";
|
||||
int32_t abcd_bits = 0;
|
||||
|
||||
if (argc < 3) {
|
||||
print_usage(stream, cli);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!strcasecmp(argv[1], "read")) {
|
||||
do_read = SWITCH_TRUE;
|
||||
chan_id = argc > 3 ? atoi(argv[3]) : 0;
|
||||
} else if (!strcasecmp(argv[1], "write") && argc >= 4) {
|
||||
const char *str = NULL;
|
||||
int mask = 0x08;
|
||||
do_read = SWITCH_FALSE;
|
||||
if (argc == 4) {
|
||||
chan_id = 0;
|
||||
write_bits_str = argv[3];
|
||||
} else {
|
||||
chan_id = atoi(argv[3]);
|
||||
write_bits_str = argv[4];
|
||||
}
|
||||
if (strlen(write_bits_str) != 4) {
|
||||
stream->write_function(stream, "-ERR Invalid CAS bits '%s'. CAS ABCD string must be composed of only four 1's and 0's (e.g. 1101)\n", write_bits_str);
|
||||
goto end;
|
||||
}
|
||||
str = write_bits_str;
|
||||
while (*str) {
|
||||
if (*str == '1') {
|
||||
abcd_bits |= mask;
|
||||
} else if (*str != '0') {
|
||||
stream->write_function(stream, "-ERR Invalid CAS bits '%s'. CAS ABCD string must be composed of only four 1's and 0's (e.g. 1101)\n", write_bits_str);
|
||||
goto end;
|
||||
}
|
||||
str++;
|
||||
mask = (mask >> 1);
|
||||
}
|
||||
} else {
|
||||
print_usage(stream, cli);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ftdm_span_find_by_name(argv[2], &span);
|
||||
if (!span) {
|
||||
stream->write_function(stream, "-ERR failed to find span %s\n", argv[2]);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (chan_id) {
|
||||
if (chan_id > ftdm_span_get_chan_count(span)) {
|
||||
stream->write_function(stream, "-ERR invalid channel\n");
|
||||
goto end;
|
||||
}
|
||||
chan = ftdm_span_get_channel(span, chan_id);
|
||||
if (do_read) {
|
||||
ftdm_channel_command(chan, FTDM_COMMAND_GET_CAS_BITS, &abcd_bits);
|
||||
stream->write_function(stream, "Read CAS bits from channel %d: %d%d%d%d (0x0%X)\n", chan_id, CASINTS(abcd_bits), abcd_bits);
|
||||
} else {
|
||||
stream->write_function(stream, "Writing 0x0%X to channel %d\n", abcd_bits, chan_id);
|
||||
}
|
||||
} else {
|
||||
iter = ftdm_span_get_chan_iterator(span, NULL);
|
||||
for (curr = iter; curr; curr = ftdm_iterator_next(curr)) {
|
||||
chan = ftdm_iterator_current(curr);
|
||||
//ftdm_channel_command();
|
||||
chan_id = ftdm_channel_get_id(chan);
|
||||
if (do_read) {
|
||||
ftdm_channel_command(chan, FTDM_COMMAND_GET_CAS_BITS, &abcd_bits);
|
||||
stream->write_function(stream, "Read CAS bits from channel %d: %d%d%d%d (0x0%X)\n", chan_id, CASINTS(abcd_bits), abcd_bits);
|
||||
} else {
|
||||
stream->write_function(stream, "Writing 0x0%X to channel %d\n", abcd_bits, chan_id);
|
||||
}
|
||||
}
|
||||
ftdm_iterator_free(iter);
|
||||
}
|
||||
stream->write_function(stream, "+OK\n");
|
||||
end:
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_API(ftdm_api_exec_usage)
|
||||
{
|
||||
char *mycmd = NULL, *argv[10] = { 0 };
|
||||
|
@ -5326,6 +5426,7 @@ static ftdm_cli_entry_t ftdm_cli_options[] =
|
|||
{ "queuesize", "<rxsize> <txsize> <span_id|span_name> [<chan_id>]", "", NULL, ftdm_cmd_queuesize, NULL },
|
||||
{ "iostats", "enable|disable|flush|print <span_id|span_name> <chan_id>", "::[enable:disable:flush:print", NULL, ftdm_cmd_iostats, NULL },
|
||||
{ "ioread", "<span_id|span_name> <chan_id> [num_times] [interval]", "", NULL, ftdm_cmd_ioread, NULL },
|
||||
{ "cas", "read|write <span_id|span_name> [<chan_id>] [<write_bits>]", "::[read:write", NULL, ftdm_cmd_cas, NULL },
|
||||
|
||||
/* Stand-alone commands (not part of the generic ftdm API */
|
||||
{ "ftdm_usage", "<span_id|span_name> <chan_id>", "", "Return channel call count", NULL, ftdm_api_exec_usage },
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
*
|
||||
*
|
||||
*/
|
||||
#ifndef _DEFAULT_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
#endif
|
||||
#define _BSD_SOURCE
|
||||
#include "private/ftdm_core.h"
|
||||
|
||||
|
|
|
@ -1489,6 +1489,16 @@ static __inline__ int chan_is_avail(ftdm_channel_t *check)
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
/* release guard time check */
|
||||
if (check->span->sig_release_guard_time_ms && check->last_release_time) {
|
||||
ftdm_time_t time_diff = (ftdm_current_time_in_ms() - check->last_release_time);
|
||||
if (time_diff < check->span->sig_release_guard_time_ms) {
|
||||
return 0;
|
||||
}
|
||||
/* circuit now available for outbound dialing */
|
||||
check->last_release_time = 0;
|
||||
ftdm_log_chan(check, FTDM_LOG_DEBUG, "Channel is now available, release guard timer expired %zdms ago\n", (time_diff - check->span->sig_release_guard_time_ms));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -2981,6 +2991,11 @@ static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan)
|
|||
ftdmchan->packet_len = ftdmchan->native_interval * (ftdmchan->effective_codec == FTDM_CODEC_SLIN ? 16 : 8);
|
||||
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE);
|
||||
}
|
||||
|
||||
if (ftdmchan->span->sig_release_guard_time_ms) {
|
||||
ftdmchan->last_release_time = ftdm_current_time_in_ms();
|
||||
}
|
||||
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "channel done\n");
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
@ -3442,7 +3457,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
|
|||
ftdmchan->dtmf_on = val;
|
||||
GOTO_STATUS(done, FTDM_SUCCESS);
|
||||
} else {
|
||||
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "invalid value %d range 10-1000", val);
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "invalid value %d range 10-1000", val);
|
||||
GOTO_STATUS(done, FTDM_FAIL);
|
||||
}
|
||||
}
|
||||
|
@ -3456,7 +3471,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
|
|||
ftdmchan->dtmf_off = val;
|
||||
GOTO_STATUS(done, FTDM_SUCCESS);
|
||||
} else {
|
||||
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "invalid value %d range 10-1000", val);
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "invalid value %d range 10-1000", val);
|
||||
GOTO_STATUS(done, FTDM_FAIL);
|
||||
}
|
||||
}
|
||||
|
@ -5096,6 +5111,12 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_channels(ftdm_span_t *span, const
|
|||
if (chan_config->dtmf_on_start) {
|
||||
span->channels[chan_index]->dtmfdetect.trigger_on_start = 1;
|
||||
}
|
||||
if (chan_config->dtmf_time_on) {
|
||||
ftdm_channel_command(span->channels[chan_index], FTDM_COMMAND_SET_DTMF_ON_PERIOD, &chan_config->dtmf_time_on);
|
||||
}
|
||||
if (chan_config->dtmf_time_off) {
|
||||
ftdm_channel_command(span->channels[chan_index], FTDM_COMMAND_SET_DTMF_OFF_PERIOD, &chan_config->dtmf_time_off);
|
||||
}
|
||||
}
|
||||
|
||||
return FTDM_SUCCESS;
|
||||
|
@ -5335,6 +5356,14 @@ static ftdm_status_t load_config(void)
|
|||
chan_config.dtmf_on_start = FTDM_FALSE;
|
||||
}
|
||||
}
|
||||
} else if (!strcasecmp(var, "dtmf_time_on")) {
|
||||
if (sscanf(val, "%u", &(chan_config.dtmf_time_on)) != 1) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "invalid dtmf_time_on: '%s'\n", val);
|
||||
}
|
||||
} else if (!strcasecmp(var, "dtmf_time_off")) {
|
||||
if (sscanf(val, "%u", &(chan_config.dtmf_time_off)) != 1) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "invalid dtmf_time_off: '%s'\n", val);
|
||||
}
|
||||
} else if (!strncasecmp(var, "iostats", sizeof("iostats")-1)) {
|
||||
if (ftdm_true(val)) {
|
||||
chan_config.iostats = FTDM_TRUE;
|
||||
|
|
|
@ -43,7 +43,7 @@ typedef enum {
|
|||
FTDM_ANALOG_POLARITY_CALLERID = (1 << 4)
|
||||
} ftdm_analog_flag_t;
|
||||
|
||||
#define FTDM_MAX_HOTLINE_STR 20
|
||||
#define FTDM_MAX_HOTLINE_STR 32
|
||||
#define MAX_DTMF 256
|
||||
|
||||
struct ftdm_analog_data {
|
||||
|
|
|
@ -44,10 +44,12 @@
|
|||
#define MAX_DIALSTRING 256
|
||||
|
||||
typedef enum {
|
||||
FTDM_ANALOG_EM_RUNNING = (1 << 0)
|
||||
FTDM_ANALOG_EM_RUNNING = (1 << 0),
|
||||
FTDM_ANALOG_EM_LOCAL_WRITE = (1 << 2),
|
||||
FTDM_ANALOG_EM_LOCAL_SUSPEND = (1 << 3),
|
||||
FTDM_ANALOG_EM_REMOTE_SUSPEND = (1 << 4),
|
||||
} ftdm_analog_em_flag_t;
|
||||
|
||||
|
||||
struct ftdm_analog_data {
|
||||
uint32_t flags;
|
||||
uint32_t max_dialstr;
|
||||
|
|
|
@ -178,8 +178,7 @@ static ftdm_status_t ftdm_analog_em_sig_write(ftdm_channel_t *ftdmchan, void *da
|
|||
ftdm_analog_em_data_t *analog_data = ftdmchan->span->signal_data;
|
||||
if (ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA
|
||||
&& analog_data->immediate_ringback
|
||||
&& ftdmchan->call_data) {
|
||||
/* DO NOT USE ftdmchan->call_data, as is a dummy non-null pointer */
|
||||
&& ftdm_test_sflag(ftdmchan, FTDM_ANALOG_EM_LOCAL_WRITE)) {
|
||||
/* ringback is being played in the analog thread, ignore user data for now */
|
||||
return FTDM_BREAK;
|
||||
}
|
||||
|
@ -283,7 +282,7 @@ static FIO_SPAN_GET_SIG_STATUS_FUNCTION(analog_em_get_span_sig_status)
|
|||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(analog_em_set_channel_sig_status)
|
||||
static ftdm_status_t analog_em_set_channel_sig_status_ex(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status, ftdm_bool_t remote)
|
||||
{
|
||||
switch (status) {
|
||||
case FTDM_SIG_STATE_DOWN:
|
||||
|
@ -299,17 +298,30 @@ static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(analog_em_set_channel_sig_status)
|
|||
}
|
||||
ftdm_analog_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_SUSPENDED);
|
||||
}
|
||||
if (remote) {
|
||||
ftdm_set_sflag(ftdmchan, FTDM_ANALOG_EM_REMOTE_SUSPEND);
|
||||
} else {
|
||||
ftdm_set_sflag(ftdmchan, FTDM_ANALOG_EM_LOCAL_SUSPEND);
|
||||
}
|
||||
break;
|
||||
case FTDM_SIG_STATE_UP:
|
||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) {
|
||||
int cas_bits = 0x00;
|
||||
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED);
|
||||
ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_CAS_BITS, &cas_bits);
|
||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK)) {
|
||||
ftdm_channel_command(ftdmchan, FTDM_COMMAND_ONHOOK, NULL);
|
||||
if (remote) {
|
||||
ftdm_clear_sflag(ftdmchan, FTDM_ANALOG_EM_REMOTE_SUSPEND);
|
||||
} else {
|
||||
ftdm_clear_sflag(ftdmchan, FTDM_ANALOG_EM_LOCAL_SUSPEND);
|
||||
}
|
||||
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) {
|
||||
ftdm_analog_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP);
|
||||
if (!ftdm_test_sflag(ftdmchan, FTDM_ANALOG_EM_REMOTE_SUSPEND) &&
|
||||
!ftdm_test_sflag(ftdmchan, FTDM_ANALOG_EM_LOCAL_SUSPEND)) {
|
||||
int cas_bits = 0x00;
|
||||
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED);
|
||||
ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_CAS_BITS, &cas_bits);
|
||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK)) {
|
||||
ftdm_channel_command(ftdmchan, FTDM_COMMAND_ONHOOK, NULL);
|
||||
}
|
||||
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) {
|
||||
ftdm_analog_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -320,6 +332,11 @@ static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(analog_em_set_channel_sig_status)
|
|||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(analog_em_set_channel_sig_status)
|
||||
{
|
||||
return analog_em_set_channel_sig_status_ex(ftdmchan, status, FTDM_FALSE);
|
||||
}
|
||||
|
||||
static FIO_SPAN_SET_SIG_STATUS_FUNCTION(analog_em_set_span_sig_status)
|
||||
{
|
||||
ftdm_iterator_t *chaniter = NULL;
|
||||
|
@ -335,7 +352,7 @@ static FIO_SPAN_SET_SIG_STATUS_FUNCTION(analog_em_set_span_sig_status)
|
|||
ftdm_channel_t *fchan = ftdm_iterator_current(citer);
|
||||
/* we set channel's state through analog_em_set_channel_sig_status(), since it already takes care of notifying the user when appropriate */
|
||||
ftdm_channel_lock(fchan);
|
||||
if ((analog_em_set_channel_sig_status(fchan, status)) != FTDM_SUCCESS) {
|
||||
if ((analog_em_set_channel_sig_status_ex(fchan, status, FTDM_FALSE)) != FTDM_SUCCESS) {
|
||||
ftdm_log_chan(fchan, FTDM_LOG_ERROR, "Failed to set signaling status to %s\n", ftdm_signaling_status2str(status));
|
||||
}
|
||||
ftdm_channel_unlock(fchan);
|
||||
|
@ -361,6 +378,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_em_configure_span)
|
|||
uint32_t digit_timeout = 2000;
|
||||
uint32_t max_dialstr = 11;
|
||||
uint32_t dial_timeout = 0;
|
||||
uint32_t release_guard_time_ms = 500;
|
||||
ftdm_bool_t answer_supervision = FTDM_FALSE;
|
||||
const char *var, *val;
|
||||
int *intval;
|
||||
|
@ -412,6 +430,11 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_em_configure_span)
|
|||
break;
|
||||
}
|
||||
max_dialstr = *intval;
|
||||
} else if (!strcasecmp(var, "release_guard_time_ms")) {
|
||||
if (!(intval = va_arg(ap, int *))) {
|
||||
break;
|
||||
}
|
||||
release_guard_time_ms = *intval;
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Invalid parameter for analog em span: '%s'\n", var);
|
||||
return FTDM_FAIL;
|
||||
|
@ -443,6 +466,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_em_configure_span)
|
|||
span->get_span_sig_status = analog_em_get_span_sig_status;
|
||||
span->set_channel_sig_status = analog_em_set_channel_sig_status;
|
||||
span->set_span_sig_status = analog_em_set_span_sig_status;
|
||||
span->sig_release_guard_time_ms = release_guard_time_ms;
|
||||
ftdm_span_load_tones(span, tonemap);
|
||||
if (immediate_ringback || !ftdm_strlen_zero(ringback_file)) {
|
||||
analog_data->immediate_ringback = FTDM_TRUE;
|
||||
|
@ -496,6 +520,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
|
|||
uint32_t cas_hangup = 0;
|
||||
int cas_answer_ms = 500;
|
||||
int cas_hangup_ms = 500;
|
||||
ftdm_bool_t busy_timeout = FTDM_FALSE;
|
||||
FILE *ringback_f = NULL;
|
||||
ftdm_bool_t digits_sent = FTDM_FALSE;
|
||||
|
||||
|
@ -762,6 +787,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
|
|||
indicate = 1;
|
||||
} else {
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
|
||||
busy_timeout = FTDM_TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -925,17 +951,25 @@ read_try:
|
|||
}
|
||||
}
|
||||
|
||||
/* we must lock the channel and make sure we let our own generated audio thru (ftdmchan->call_data is tested in the ftdm_analog_em_sig_write handler)*/
|
||||
/* we must lock the channel and make sure we let our own generated audio thru (FTDM_ANALOG_EM_LOCAL_WRITE is tested in the ftdm_analog_em_sig_write handler)*/
|
||||
ftdm_channel_lock(ftdmchan);
|
||||
ftdmchan->call_data = (void *)0xFF; /* ugh! */
|
||||
ftdm_set_sflag(ftdmchan, FTDM_ANALOG_EM_LOCAL_WRITE);
|
||||
ftdm_channel_write(ftdmchan, frame, sizeof(frame), &rlen);
|
||||
ftdmchan->call_data = NULL;
|
||||
ftdm_clear_sflag(ftdmchan, FTDM_ANALOG_EM_LOCAL_WRITE);
|
||||
ftdm_channel_unlock(ftdmchan);
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
ftdm_channel_command(ftdmchan, FTDM_COMMAND_ONHOOK, NULL);
|
||||
if (busy_timeout) {
|
||||
ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_CAS_BITS, &cas_bits);
|
||||
if (cas_bits == 0XF) {
|
||||
/* the remote end never sent any digits, neither moved to onhook, let's stay suspended */
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Moving channel to suspended after timeout, remote end still offhook\n");
|
||||
analog_em_set_channel_sig_status_ex(ftdmchan, FTDM_SIG_STATE_SUSPENDED, FTDM_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
closed_chan = ftdmchan;
|
||||
ftdm_channel_close(&ftdmchan);
|
||||
|
@ -984,6 +1018,11 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
|
|||
ftdm_mutex_lock(event->channel->mutex);
|
||||
locked++;
|
||||
|
||||
if (event->enum_id == FTDM_OOB_ONHOOK && ftdm_test_sflag(event->channel, FTDM_ANALOG_EM_REMOTE_SUSPEND)) {
|
||||
/* We've got remote suspend, now we're back on hook, lift the remote suspend status */
|
||||
analog_em_set_channel_sig_status_ex(event->channel, FTDM_SIG_STATE_UP, FTDM_TRUE);
|
||||
}
|
||||
|
||||
if (ftdm_test_flag(event->channel, FTDM_CHANNEL_SUSPENDED)) {
|
||||
ftdm_log(FTDM_LOG_WARNING, "Ignoring event %s on channel %d:%d in state %s, channel is suspended\n",
|
||||
ftdm_oob_event2str(event->enum_id), event->channel->span_id, event->channel->chan_id, ftdm_channel_state2str(event->channel->state));
|
||||
|
|
|
@ -38,6 +38,9 @@
|
|||
*/
|
||||
|
||||
#ifdef __linux__
|
||||
#ifndef _DEFAULT_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
#endif
|
||||
#ifndef _BSD_SOURCE
|
||||
#define _BSD_SOURCE /* for strsep() */
|
||||
#endif
|
||||
|
|
|
@ -203,8 +203,17 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
if (signal_data->overlap_dial == SNGISDN_OPT_TRUE && !conEvnt->sndCmplt.eh.pres) {
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT);
|
||||
if (signal_data->overlap_dial == SNGISDN_OPT_TRUE) {
|
||||
ftdm_size_t min_digits = ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->min_digits;
|
||||
ftdm_size_t num_digits;
|
||||
|
||||
num_digits = strlen(ftdmchan->caller_data.dnis.digits);
|
||||
|
||||
if (conEvnt->sndCmplt.eh.pres || num_digits >= min_digits) {
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
|
||||
} else {
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT);
|
||||
}
|
||||
} else {
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
|
||||
}
|
||||
|
|
|
@ -40,6 +40,9 @@
|
|||
*
|
||||
*/
|
||||
#ifdef WP_DEBUG_IO
|
||||
#ifndef _DEFAULT_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
#endif
|
||||
#define _BSD_SOURCE
|
||||
#include <syscall.h>
|
||||
#endif
|
||||
|
|
|
@ -74,10 +74,10 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
/*! \brief Limit to span names */
|
||||
#define FTDM_MAX_NAME_STR_SZ 80
|
||||
#define FTDM_MAX_NAME_STR_SZ 128
|
||||
|
||||
/*! \brief Limit to channel number strings */
|
||||
#define FTDM_MAX_NUMBER_STR_SZ 20
|
||||
#define FTDM_MAX_NUMBER_STR_SZ 32
|
||||
|
||||
/*! \brief Hangup cause codes */
|
||||
typedef enum {
|
||||
|
@ -355,7 +355,7 @@ typedef enum {
|
|||
FTDM_STR2ENUM_P(ftdm_str2ftdm_transfer_response, ftdm_transfer_response2str, ftdm_transfer_response_t)
|
||||
|
||||
/*! \brief Digit limit used in DNIS/ANI */
|
||||
#define FTDM_DIGITS_LIMIT 25
|
||||
#define FTDM_DIGITS_LIMIT 64
|
||||
|
||||
#define FTDM_SILENCE_VALUE(fchan) (fchan)->native_codec == FTDM_CODEC_ULAW ? 255 : (fchan)->native_codec == FTDM_CODEC_ALAW ? 0xD5 : 0x00
|
||||
|
||||
|
@ -533,6 +533,8 @@ typedef struct ftdm_channel_config {
|
|||
uint8_t debugdtmf;
|
||||
uint8_t dtmf_on_start;
|
||||
uint32_t dtmfdetect_ms;
|
||||
uint32_t dtmf_time_on;
|
||||
uint32_t dtmf_time_off;
|
||||
uint8_t iostats;
|
||||
} ftdm_channel_config_t;
|
||||
|
||||
|
|
|
@ -477,6 +477,7 @@ struct ftdm_channel {
|
|||
int32_t rxdrops;
|
||||
ftdm_usrmsg_t *usrmsg;
|
||||
ftdm_time_t last_state_change_time;
|
||||
ftdm_time_t last_release_time;
|
||||
};
|
||||
|
||||
struct ftdm_span {
|
||||
|
@ -515,6 +516,7 @@ struct ftdm_span {
|
|||
ftdm_channel_sig_write_t sig_write;
|
||||
ftdm_channel_sig_dtmf_t sig_queue_dtmf;
|
||||
ftdm_channel_sig_dtmf_t sig_send_dtmf;
|
||||
uint32_t sig_release_guard_time_ms;
|
||||
ftdm_channel_state_processor_t state_processor; /*!< This guy is called whenever state processing is required */
|
||||
void *io_data; /*!< Private I/O data per span. Do not touch unless you are an I/O module */
|
||||
char *type;
|
||||
|
|
|
@ -226,7 +226,7 @@ void iks_disconnect (iksparser *prs);
|
|||
int iks_has_tls (void);
|
||||
int iks_is_secure (iksparser *prs);
|
||||
int iks_start_tls (iksparser *prs);
|
||||
int iks_proceed_tls (iksparser *prs, const char *cert_file, const char *key_file, int use_ssl);
|
||||
int iks_proceed_tls (iksparser *prs, const char *cert_file, const char *key_file);
|
||||
int iks_start_sasl (iksparser *prs, enum ikssasltype type, char *username, char *pass);
|
||||
|
||||
/***** jabber *****/
|
||||
|
|
|
@ -36,7 +36,6 @@ typedef unsigned __int32 uint32_t;
|
|||
#define SF_TRY_SECURE 2
|
||||
#define SF_SECURE 4
|
||||
#define SF_SERVER 8
|
||||
#define SF_SSLv23 16
|
||||
|
||||
struct stream_data {
|
||||
iksparser *prs;
|
||||
|
@ -319,11 +318,7 @@ handshake (struct stream_data *data)
|
|||
SSL_load_error_strings();
|
||||
|
||||
if (data->flags & SF_SERVER) {
|
||||
if (data->flags & SF_SSLv23) {
|
||||
data->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
|
||||
} else {
|
||||
data->ssl_ctx = SSL_CTX_new(TLSv1_server_method());
|
||||
}
|
||||
data->ssl_ctx = SSL_CTX_new(TLSv1_server_method());
|
||||
if(!data->ssl_ctx) return IKS_NOMEM;
|
||||
|
||||
if (SSL_CTX_use_certificate_file(data->ssl_ctx, data->cert_file, SSL_FILETYPE_PEM) <= 0) {
|
||||
|
@ -985,7 +980,7 @@ iks_start_tls (iksparser *prs)
|
|||
}
|
||||
|
||||
int
|
||||
iks_proceed_tls (iksparser *prs, const char *cert_file, const char *key_file, int use_ssl)
|
||||
iks_proceed_tls (iksparser *prs, const char *cert_file, const char *key_file)
|
||||
{
|
||||
#ifdef HAVE_GNUTLS
|
||||
int ret;
|
||||
|
@ -996,9 +991,6 @@ iks_proceed_tls (iksparser *prs, const char *cert_file, const char *key_file, in
|
|||
data->cert_file = iks_stack_strdup(data->s, cert_file, 0);
|
||||
data->key_file = iks_stack_strdup(data->s, key_file, 0);
|
||||
data->flags |= SF_TRY_SECURE | SF_SERVER;
|
||||
if (use_ssl) {
|
||||
data->flags |= SF_SSLv23;
|
||||
}
|
||||
return handshake (data);
|
||||
#elif HAVE_SSL
|
||||
int ret;
|
||||
|
@ -1009,9 +1001,6 @@ iks_proceed_tls (iksparser *prs, const char *cert_file, const char *key_file, in
|
|||
data->cert_file = iks_stack_strdup(data->s, cert_file, 0);
|
||||
data->key_file = iks_stack_strdup(data->s, key_file, 0);
|
||||
data->flags |= SF_TRY_SECURE | SF_SERVER;
|
||||
if (use_ssl) {
|
||||
data->flags |= SF_SSLv23;
|
||||
}
|
||||
return handshake (data);
|
||||
#else
|
||||
return IKS_NET_NOTSUPP;
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
#ifdef __linux__
|
||||
#ifndef _DEFAULT_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
#endif
|
||||
#define _BSD_SOURCE 1
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
|
|
@ -101,6 +101,18 @@
|
|||
*/
|
||||
#define ZRTP_BYTE_ORDER ZBO_BIG_ENDIAN
|
||||
|
||||
#elif defined(__MIPSEB__)
|
||||
/*
|
||||
* mips, big endian
|
||||
*/
|
||||
#define ZRTP_BYTE_ORDER ZBO_BIG_ENDIAN
|
||||
|
||||
#elif defined(__MIPSEL__)
|
||||
/*
|
||||
* mips, little endian
|
||||
*/
|
||||
#define ZRTP_BYTE_ORDER ZBO_LITTLE_ENDIAN
|
||||
|
||||
#endif /* Automatic byte order detection */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1 +1 @@
|
|||
Fri Oct 31 13:48:09 CDT 2014
|
||||
Wed Nov 12 13:07:56 CST 2014
|
||||
|
|
|
@ -3188,7 +3188,9 @@ int agent_check_request_via(nta_agent_t *agent,
|
|||
else if (agent->sa_server_rport == 2 ||
|
||||
(agent->sa_server_rport == 3 && sip && sip->sip_user_agent &&
|
||||
sip->sip_user_agent->g_string &&
|
||||
(!strncasecmp(sip->sip_user_agent->g_string, "Polycom", 7) || !strncasecmp(sip->sip_user_agent->g_string, "KIRK Wireless Server", 20)))) {
|
||||
(!strncasecmp(sip->sip_user_agent->g_string, "Polycom", 7) ||
|
||||
!strncasecmp(sip->sip_user_agent->g_string, "KIRK Wireless Server", 20) ||
|
||||
!strncasecmp(sip->sip_user_agent->g_string, "ADTRAN_Total_Access", 19)))) {
|
||||
rport = su_sprintf(msg_home(msg), "rport=%u", ntohs(from->su_port));
|
||||
msg_header_replace_param(msg_home(msg), v->v_common, rport);
|
||||
}
|
||||
|
|
|
@ -1549,10 +1549,12 @@ static void nua_session_usage_refresh(nua_handle_t *nh,
|
|||
nua_client_request_in_progress(cr))
|
||||
return;
|
||||
|
||||
if (ds->ds_cr) return; /* request queued */
|
||||
|
||||
/* UPDATE has been queued */
|
||||
for (cr = ds->ds_cr; cr; cr = cr->cr_next)
|
||||
if (cr->cr_method == sip_method_update)
|
||||
return;
|
||||
//for (cr = ds->ds_cr; cr; cr = cr->cr_next)
|
||||
//if (cr->cr_method == sip_method_update)
|
||||
// return;
|
||||
|
||||
/* INVITE or UPDATE in progress on server side */
|
||||
for (sr = ds->ds_sr; sr; sr = sr->sr_next)
|
||||
|
|
|
@ -34,6 +34,9 @@
|
|||
|
||||
#define _XOPEN_SOURCE 600 /* For strdup() */
|
||||
#define _BSD_SOURCE /* For xmlrpc_strcaseeq */
|
||||
#ifndef _DEFAULT_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
#define _XOPEN_SOURCE 600 /* For strdup() */
|
||||
#define _BSD_SOURCE /* For xmlrpc_strcaseeq() */
|
||||
#ifndef _DEFAULT_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
#define _XOPEN_SOURCE 600 /* Make sure strdup() is in <string.h> */
|
||||
#define _BSD_SOURCE /* Make sure setgroups()is in <grp.h> */
|
||||
#ifndef _DEFAULT_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
#!/usr/bin/perl
|
||||
#
|
||||
# Make bulk gateway xml from csv file.
|
||||
#
|
||||
|
||||
open(CSV, "gateways.csv");
|
||||
my @data = <CSV>;
|
||||
close(CSV);
|
||||
|
||||
foreach my $line (@data) {
|
||||
chomp($line);
|
||||
my ($gwname, $username, $password) = split(/,/, $line);
|
||||
print <<XML;
|
||||
<gateway name="$gwname">
|
||||
<param name="username" value="$username"/>
|
||||
<!--<param name="realm" value="asterlink.com"/>-->
|
||||
<!--<param name="from-user" value="cluecon"/>-->
|
||||
<!--<param name="from-domain" value="asterlink.com"/>-->
|
||||
<param name="password" value="$password"/>
|
||||
<!--<param name="extension" value="cluecon"/>-->
|
||||
<!--<param name="proxy" value="asterlink.com"/>-->
|
||||
<!--<param name="register-proxy" value="mysbc.com"/>-->
|
||||
<!--<param name="expire-seconds" value="60"/>-->
|
||||
<!--<param name="register" value="false"/>-->
|
||||
<!--<param name="register-transport" value="udp"/>-->
|
||||
<!--<param name="retry-seconds" value="30"/>-->
|
||||
<!--<param name="caller-id-in-from" value="false"/>-->
|
||||
<!--<param name="contact-params" value=""/>-->
|
||||
<!--<param name="extension-in-contact" value="true"/>-->
|
||||
<!--<param name="ping" value="25"/>-->
|
||||
<!--<param name="cid-type" value="rpid"/>-->
|
||||
<!--<param name="rfc-5626" value="true"/>-->
|
||||
<!--<param name="reg-id" value="1"/>-->
|
||||
</gateway>
|
||||
XML
|
||||
|
||||
}
|
|
@ -63,6 +63,9 @@
|
|||
#ifndef _BSD_SOURCE
|
||||
#define _BSD_SOURCE
|
||||
#endif
|
||||
#ifndef _DEFAULT_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
#endif
|
||||
#endif
|
||||
#ifndef __BSD_VISIBLE
|
||||
#define __BSD_VISIBLE 1
|
||||
|
|
|
@ -146,6 +146,15 @@ typedef struct switch_core_media_params_s {
|
|||
switch_core_media_dtmf_t dtmf_type;
|
||||
switch_payload_t cng_pt;
|
||||
|
||||
/* a core_video_thread will be started automatically
|
||||
when uses rtp based media,
|
||||
external_video_source should be set to SWITCH_TRUE and
|
||||
switch_core_media_start_video_thread()
|
||||
should be explicitly called to start the video thread
|
||||
if uses the media handle for non-rtp based media
|
||||
*/
|
||||
switch_bool_t external_video_source;
|
||||
|
||||
} switch_core_media_params_t;
|
||||
|
||||
static inline const char *switch_media_type2str(switch_media_type_t type)
|
||||
|
@ -252,6 +261,7 @@ SWITCH_DECLARE(void) switch_core_media_deinit(void);
|
|||
SWITCH_DECLARE(void) switch_core_media_set_stats(switch_core_session_t *session);
|
||||
SWITCH_DECLARE(void) switch_core_session_wake_video_thread(switch_core_session_t *session);
|
||||
SWITCH_DECLARE(void) switch_core_session_clear_crypto(switch_core_session_t *session);
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_media_start_video_thread(switch_core_session_t *session);
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_session_get_payload_code(switch_core_session_t *session,
|
||||
switch_media_type_t type,
|
||||
|
|
|
@ -361,7 +361,8 @@ typedef enum {
|
|||
SCF_CORE_NON_SQLITE_DB_REQ = (1 << 20),
|
||||
SCF_DEBUG_SQL = (1 << 21),
|
||||
SCF_API_EXPANSION = (1 << 22),
|
||||
SCF_SESSION_THREAD_POOL = (1 << 23)
|
||||
SCF_SESSION_THREAD_POOL = (1 << 23),
|
||||
SCF_DIALPLAN_TIMESTAMPS = (1 << 24)
|
||||
} switch_core_flag_enum_t;
|
||||
typedef uint32_t switch_core_flag_t;
|
||||
|
||||
|
|
|
@ -541,6 +541,28 @@ SWITCH_DECLARE(int) switch_build_uri(char *uri, switch_size_t size, const char *
|
|||
|
||||
#define SWITCH_STATUS_IS_BREAK(x) (x == SWITCH_STATUS_BREAK || x == 730035 || x == 35 || x == SWITCH_STATUS_INTR)
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#define switch_errno() WSAGetLastError()
|
||||
|
||||
static inline int switch_errno_is_break(int errcode)
|
||||
{
|
||||
return errcode == WSAEWOULDBLOCK || errcode == WSAEINPROGRESS || errcode == WSAEINTR;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define switch_errno() errno
|
||||
|
||||
static inline int switch_errno_is_break(int errcode)
|
||||
{
|
||||
return errcode == EAGAIN || errcode == EWOULDBLOCK || errcode == EINPROGRESS || errcode == EINTR || errcode == ETIMEDOUT;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
\brief Return a printable name of a switch_priority_t
|
||||
\param priority the priority to get the name of
|
||||
|
|
|
@ -2277,7 +2277,8 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
|
|||
}
|
||||
|
||||
if (conference->count > 1) {
|
||||
if (conference->moh_sound && !switch_test_flag(conference, CFLAG_WAIT_MOD)) {
|
||||
if ((conference->moh_sound && !switch_test_flag(conference, CFLAG_WAIT_MOD)) ||
|
||||
(switch_test_flag(conference, CFLAG_WAIT_MOD) && !switch_true(switch_channel_get_variable(channel, "conference_permanent_wait_mod_moh")))) {
|
||||
/* stop MoH if any */
|
||||
conference_stop_file(conference, FILE_STOP_ASYNC);
|
||||
}
|
||||
|
@ -2287,10 +2288,9 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
|
|||
if (switch_test_flag(conference, CFLAG_ENTER_SOUND)) {
|
||||
if (!zstr(enter_sound)) {
|
||||
conference_play_file(conference, (char *)enter_sound, CONF_DEFAULT_LEADIN,
|
||||
switch_core_session_get_channel(member->session), !switch_test_flag(conference, CFLAG_WAIT_MOD) ? 0 : 1);
|
||||
switch_core_session_get_channel(member->session), 0);
|
||||
} else {
|
||||
conference_play_file(conference, conference->enter_sound, CONF_DEFAULT_LEADIN, switch_core_session_get_channel(member->session),
|
||||
!switch_test_flag(conference, CFLAG_WAIT_MOD) ? 0 : 1);
|
||||
conference_play_file(conference, conference->enter_sound, CONF_DEFAULT_LEADIN, switch_core_session_get_channel(member->session), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2316,7 +2316,7 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
|
|||
if (conference->alone_sound && !switch_test_flag(member, MFLAG_GHOST)) {
|
||||
conference_stop_file(conference, FILE_STOP_ASYNC);
|
||||
conference_play_file(conference, conference->alone_sound, CONF_DEFAULT_LEADIN,
|
||||
switch_core_session_get_channel(member->session), 1);
|
||||
switch_core_session_get_channel(member->session), 0);
|
||||
} else {
|
||||
switch_snprintf(msg, sizeof(msg), "You are currently the only person in this conference.");
|
||||
conference_member_say(member, msg, CONF_DEFAULT_LEADIN);
|
||||
|
@ -2683,7 +2683,7 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe
|
|||
|
||||
if (member->session && (exit_sound = switch_channel_get_variable(switch_core_session_get_channel(member->session), "conference_exit_sound"))) {
|
||||
conference_play_file(conference, (char *)exit_sound, CONF_DEFAULT_LEADIN,
|
||||
switch_core_session_get_channel(member->session), !switch_test_flag(conference, CFLAG_WAIT_MOD) ? 0 : 1);
|
||||
switch_core_session_get_channel(member->session), 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2786,12 +2786,16 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe
|
|||
|| (switch_test_flag(conference, CFLAG_DYNAMIC) && (conference->count + conference->count_ghosts == 0))) {
|
||||
switch_set_flag(conference, CFLAG_DESTRUCT);
|
||||
} else {
|
||||
if (!switch_true(switch_channel_get_variable(channel, "conference_permanent_wait_mod_moh")) && switch_test_flag(conference, CFLAG_WAIT_MOD)) {
|
||||
/* Stop MOH if any */
|
||||
conference_stop_file(conference, FILE_STOP_ASYNC);
|
||||
}
|
||||
if (!exit_sound && conference->exit_sound && switch_test_flag(conference, CFLAG_EXIT_SOUND)) {
|
||||
conference_play_file(conference, conference->exit_sound, 0, channel, 0);
|
||||
}
|
||||
if (conference->count == 1 && conference->alone_sound && !switch_test_flag(conference, CFLAG_WAIT_MOD) && !switch_test_flag(member, MFLAG_GHOST)) {
|
||||
conference_stop_file(conference, FILE_STOP_ASYNC);
|
||||
conference_play_file(conference, conference->alone_sound, 0, channel, 1);
|
||||
conference_play_file(conference, conference->alone_sound, 0, channel, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3146,7 +3150,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
|
|||
if (conference->perpetual_sound && !conference->async_fnode) {
|
||||
conference_play_file(conference, conference->perpetual_sound, CONF_DEFAULT_LEADIN, NULL, 1);
|
||||
} else if (conference->moh_sound && ((nomoh == 0 && conference->count == 1)
|
||||
|| switch_test_flag(conference, CFLAG_WAIT_MOD)) && !conference->async_fnode) {
|
||||
|| switch_test_flag(conference, CFLAG_WAIT_MOD)) && !conference->async_fnode && !conference->fnode) {
|
||||
conference_play_file(conference, conference->moh_sound, CONF_DEFAULT_LEADIN, NULL, 1);
|
||||
}
|
||||
|
||||
|
@ -6143,7 +6147,7 @@ static switch_status_t conf_api_sub_mute(conference_member_t *member, switch_str
|
|||
switch_clear_flag_locked(member, MFLAG_CAN_SPEAK);
|
||||
switch_clear_flag_locked(member, MFLAG_TALKING);
|
||||
|
||||
if (member->session && !switch_test_flag(member, MFLAG_INDICATE_MUTE)) {
|
||||
if (member->session && !switch_test_flag(member, MFLAG_MUTE_DETECT)) {
|
||||
switch_core_media_hard_mute(member->session, SWITCH_TRUE);
|
||||
}
|
||||
|
||||
|
@ -6241,7 +6245,7 @@ static switch_status_t conf_api_sub_unmute(conference_member_t *member, switch_s
|
|||
|
||||
switch_set_flag_locked(member, MFLAG_CAN_SPEAK);
|
||||
|
||||
if (member->session && !switch_test_flag(member, MFLAG_INDICATE_MUTE)) {
|
||||
if (member->session && !switch_test_flag(member, MFLAG_MUTE_DETECT)) {
|
||||
switch_core_media_hard_mute(member->session, SWITCH_FALSE);
|
||||
}
|
||||
|
||||
|
@ -8757,6 +8761,8 @@ static void set_mflags(const char *flags, member_flag_t *f)
|
|||
char *argv[10] = { 0 };
|
||||
int i, argc = 0;
|
||||
|
||||
*f |= MFLAG_CAN_SPEAK | MFLAG_CAN_HEAR;
|
||||
|
||||
for (p = dup; p && *p; p++) {
|
||||
if (*p == ',') {
|
||||
*p = '|';
|
||||
|
@ -9081,6 +9087,7 @@ SWITCH_STANDARD_APP(conference_function)
|
|||
char *profile_name = NULL;
|
||||
switch_xml_t cxml = NULL, cfg = NULL, profiles = NULL;
|
||||
const char *flags_str, *v_flags_str;
|
||||
const char *cflags_str, *v_cflags_str;
|
||||
member_flag_t mflags = 0;
|
||||
switch_core_session_message_t msg = { 0 };
|
||||
uint8_t rl = 0, isbr = 0;
|
||||
|
@ -9144,6 +9151,16 @@ SWITCH_STANDARD_APP(conference_function)
|
|||
}
|
||||
}
|
||||
|
||||
cflags_str = flags_str;
|
||||
|
||||
if ((v_cflags_str = switch_channel_get_variable(channel, "conference_flags"))) {
|
||||
if (zstr(cflags_str)) {
|
||||
cflags_str = v_cflags_str;
|
||||
} else {
|
||||
cflags_str = switch_core_session_sprintf(session, "%s|%s", cflags_str, v_cflags_str);
|
||||
}
|
||||
}
|
||||
|
||||
/* is this a bridging conference ? */
|
||||
if (!strncasecmp(mydata, bridge_prefix, strlen(bridge_prefix))) {
|
||||
isbr = 1;
|
||||
|
@ -9234,6 +9251,8 @@ SWITCH_STANDARD_APP(conference_function)
|
|||
goto done;
|
||||
}
|
||||
|
||||
set_cflags(cflags_str, &conference->flags);
|
||||
|
||||
if (locked) {
|
||||
switch_mutex_unlock(globals.setup_mutex);
|
||||
locked = 0;
|
||||
|
@ -9279,7 +9298,7 @@ SWITCH_STANDARD_APP(conference_function)
|
|||
set_mflags(flags_str,&mflags);
|
||||
|
||||
if (!(mflags & MFLAG_CAN_SPEAK)) {
|
||||
if (!(mflags & MFLAG_INDICATE_MUTE)) {
|
||||
if (!(mflags & MFLAG_MUTE_DETECT)) {
|
||||
switch_core_media_hard_mute(session, SWITCH_TRUE);
|
||||
}
|
||||
}
|
||||
|
@ -9316,6 +9335,8 @@ SWITCH_STANDARD_APP(conference_function)
|
|||
goto done;
|
||||
}
|
||||
|
||||
set_cflags(cflags_str, &conference->flags);
|
||||
|
||||
if (locked) {
|
||||
switch_mutex_unlock(globals.setup_mutex);
|
||||
locked = 0;
|
||||
|
@ -9582,7 +9603,7 @@ SWITCH_STANDARD_APP(conference_function)
|
|||
mflags |= MFLAG_RUNNING;
|
||||
|
||||
if (!(mflags & MFLAG_CAN_SPEAK)) {
|
||||
if (!(mflags & MFLAG_INDICATE_MUTE)) {
|
||||
if (!(mflags & MFLAG_MUTE_DETECT)) {
|
||||
switch_core_media_hard_mute(member.session, SWITCH_TRUE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_curl_load);
|
|||
*/
|
||||
SWITCH_MODULE_DEFINITION(mod_curl, mod_curl_load, mod_curl_shutdown, NULL);
|
||||
|
||||
static char *SYNTAX = "curl url [headers|json|content-type <mime-type>|timeout <seconds>] [get|head|post|delete|put [data]]";
|
||||
static char *SYNTAX = "curl url [headers|json|content-type <mime-type>|connect-timeout <seconds>|timeout <seconds>] [get|head|post|delete|put [data]]";
|
||||
|
||||
#define HTTP_SENDFILE_ACK_EVENT "curl_sendfile::ack"
|
||||
#define HTTP_SENDFILE_RESPONSE_SIZE 32768
|
||||
|
@ -241,6 +241,7 @@ static http_data_t *do_lookup_url(switch_memory_pool_t *pool, const char *url, c
|
|||
}
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 15);
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_URL, url);
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, file_callback);
|
||||
|
@ -944,12 +945,22 @@ SWITCH_STANDARD_API(curl_function)
|
|||
if (++i < argc) {
|
||||
content_type = switch_core_strdup(pool, argv[i]);
|
||||
}
|
||||
} else if (!strcasecmp("timeout", argv[i])) {
|
||||
} else if (!strcasecmp("connect-timeout", argv[i])) {
|
||||
if (++i < argc) {
|
||||
int tmp = atoi(argv[i]);
|
||||
|
||||
if (tmp > 0) {
|
||||
options.connect_timeout = tmp;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Invalid connect-timeout!\n");
|
||||
}
|
||||
}
|
||||
} else if (!strcasecmp("timeout", argv[i])) {
|
||||
if (++i < argc) {
|
||||
int tmp = atoi(argv[i]);
|
||||
|
||||
if (tmp > 0) {
|
||||
options.timeout = tmp;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Invalid timeout!\n");
|
||||
}
|
||||
|
|
|
@ -79,6 +79,15 @@ SWITCH_MODULE_DEFINITION(mod_fifo, mod_fifo_load, mod_fifo_shutdown, NULL);
|
|||
* The /enterprise/ outbound strategy does not preserve the caller ID
|
||||
* of the caller thereby allowing deliver of callers to agents at the
|
||||
* fastest possible rate.
|
||||
*
|
||||
* outbound_per_cycle is used to define the maximum number of agents
|
||||
* who will be available to answer a single caller. In ringall this
|
||||
* maximum is the number who will be called, in enterprise the need defines
|
||||
* how many agents will be called. outbound_per_cycle_min will define
|
||||
* the minimum agents who will be called to answer a caller regardless of
|
||||
* need, giving the enterprise strategy the ability to ring through more
|
||||
* than one agent for one caller.
|
||||
|
||||
*
|
||||
* ## Manual calls
|
||||
*
|
||||
|
@ -391,6 +400,7 @@ struct fifo_node {
|
|||
long busy;
|
||||
int is_static;
|
||||
int outbound_per_cycle;
|
||||
int outbound_per_cycle_min;
|
||||
char *outbound_name;
|
||||
outbound_strategy_t outbound_strategy;
|
||||
int ring_timeout;
|
||||
|
@ -1985,6 +1995,21 @@ static int place_call_enterprise_callback(void *pArg, int argc, char **argv, cha
|
|||
* the results. The enterprise strategy handler can simply take each
|
||||
* member one at a time, so the `place_call_enterprise_callback` takes
|
||||
* care of invoking the handler.
|
||||
*
|
||||
* Within the ringall call strategy outbound_per_cycle is used to define
|
||||
* how many agents exactly are assigned to the caller. With ringall if
|
||||
* multiple callers are calling in and one is answered, because the call
|
||||
* is assigned to all agents the call to the agents that is not answered
|
||||
* will be lose raced and the other agents will drop the call before the
|
||||
* next one will begin to ring. When oubound_per_cycle is used in the
|
||||
* enterprise strategy it acts as a maximum value for how many agents
|
||||
* are rung at once on any call, the caller is not assigned to any agent
|
||||
* until the call is answered. Enterprise only rings the number of phones
|
||||
* that are needed, so outbound_per_cycle as a max does not give you the
|
||||
* effect of ringall. outbound_per_cycle_min defines how many agents minimum
|
||||
* will be rung by an incoming caller through fifo, which can give a ringall
|
||||
* effect. outbound_per_cycle and outbound_per_cycle_min both default to 1.
|
||||
*
|
||||
*/
|
||||
static void find_consumers(fifo_node_t *node)
|
||||
{
|
||||
|
@ -2005,6 +2030,8 @@ static void find_consumers(fifo_node_t *node)
|
|||
|
||||
if (node->outbound_per_cycle && node->outbound_per_cycle < need) {
|
||||
need = node->outbound_per_cycle;
|
||||
} else if (node->outbound_per_cycle_min && node->outbound_per_cycle_min > need) {
|
||||
need = node->outbound_per_cycle_min;
|
||||
}
|
||||
|
||||
fifo_execute_sql_callback(globals.sql_mutex, sql, place_call_enterprise_callback, &need);
|
||||
|
@ -4045,6 +4072,9 @@ static void list_node(fifo_node_t *node, switch_xml_t x_report, int *off, int ve
|
|||
switch_snprintf(tmp, sizeof(buffer), "%u", node->outbound_per_cycle);
|
||||
switch_xml_set_attr_d(x_fifo, "outbound_per_cycle", tmp);
|
||||
|
||||
switch_snprintf(tmp, sizeof(buffer), "%u", node->outbound_per_cycle_min);
|
||||
switch_xml_set_attr_d(x_fifo, "outbound_per_cycle_min", tmp);
|
||||
|
||||
switch_snprintf(tmp, sizeof(buffer), "%u", node->ring_timeout);
|
||||
switch_xml_set_attr_d(x_fifo, "ring_timeout", tmp);
|
||||
|
||||
|
@ -4088,6 +4118,7 @@ void node_dump(switch_stream_handle_t *stream)
|
|||
stream->write_function(stream, "node: %s\n"
|
||||
" outbound_name: %s\n"
|
||||
" outbound_per_cycle: %d"
|
||||
" outbound_per_cycle_min: %d"
|
||||
" outbound_priority: %d"
|
||||
" outbound_strategy: %s\n"
|
||||
" has_outbound: %d\n"
|
||||
|
@ -4096,7 +4127,7 @@ void node_dump(switch_stream_handle_t *stream)
|
|||
" ready: %d\n"
|
||||
" waiting: %d\n"
|
||||
,
|
||||
node->name, node->outbound_name, node->outbound_per_cycle,
|
||||
node->name, node->outbound_name, node->outbound_per_cycle, node->outbound_per_cycle_min,
|
||||
node->outbound_priority, print_strategy(node->outbound_strategy),
|
||||
node->has_outbound,
|
||||
node->outbound_priority,
|
||||
|
@ -4508,6 +4539,13 @@ static switch_status_t load_config(int reload, int del_all)
|
|||
node->has_outbound = 1;
|
||||
}
|
||||
|
||||
node->outbound_per_cycle_min = 1;
|
||||
if ((val = switch_xml_attr(fifo, "outbound_per_cycle_min"))) {
|
||||
if (!((i = atoi(val)) < 0)) {
|
||||
node->outbound_per_cycle_min = i;
|
||||
}
|
||||
}
|
||||
|
||||
if ((val = switch_xml_attr(fifo, "retry_delay"))) {
|
||||
if ((i = atoi(val)) < 0) i = 0;
|
||||
node->retry_delay = i;
|
||||
|
|
|
@ -155,6 +155,7 @@ static struct {
|
|||
int not_found_expires;
|
||||
int cache_ttl;
|
||||
int abs_cache_ttl;
|
||||
client_profile_t *profile;
|
||||
} globals;
|
||||
|
||||
|
||||
|
@ -1624,10 +1625,19 @@ static switch_status_t httapi_sync(client_t *client)
|
|||
if (client->profile->ssl_version) {
|
||||
if (!strcasecmp(client->profile->ssl_version, "SSLv3")) {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3);
|
||||
} else if (!strcasecmp(client->profile->ssl_version, "TLSv1")) {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
|
||||
#ifdef CURL_SSLVERSION_TLSv1_1
|
||||
} else if (!strcasecmp(client->profile->ssl_version, "TLSv1.1")) {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_1);
|
||||
#endif
|
||||
#ifdef CURL_SSLVERSION_TLSv1_2
|
||||
} else if (!strcasecmp(client->profile->ssl_version, "TLSv1.2")) {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
|
||||
}
|
||||
|
||||
|
||||
if (client->profile->ssl_cacert_file) {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_CAINFO, client->profile->ssl_cacert_file);
|
||||
|
@ -2150,6 +2160,8 @@ static switch_status_t do_config(void)
|
|||
|
||||
profile->name = switch_core_strdup(globals.pool, bname);
|
||||
|
||||
if (!globals.profile) globals.profile = profile;
|
||||
|
||||
switch_core_hash_insert(globals.profile_hash, bname, profile);
|
||||
|
||||
x++;
|
||||
|
@ -2429,16 +2441,33 @@ static size_t save_file_callback(void *ptr, size_t size, size_t nmemb, void *dat
|
|||
static switch_status_t fetch_cache_data(http_file_context_t *context, const char *url, switch_event_t **headers, const char *save_path)
|
||||
{
|
||||
switch_CURL *curl_handle = NULL;
|
||||
client_t client = { 0 };
|
||||
client_t *client = NULL;
|
||||
long code;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
char *dup_creds = NULL, *dynamic_url = NULL, *use_url;
|
||||
char *ua = NULL;
|
||||
const char *profile_name = NULL;
|
||||
|
||||
|
||||
if (context->url_params) {
|
||||
profile_name = switch_event_get_header(context->url_params, "profile_name");
|
||||
}
|
||||
|
||||
if (zstr(profile_name)) {
|
||||
if (globals.profile) profile_name = globals.profile->name;
|
||||
}
|
||||
|
||||
if (zstr(profile_name)) {
|
||||
profile_name = "default";
|
||||
}
|
||||
|
||||
if (!(client = client_create(NULL, profile_name, NULL))) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
client.fd = -1;
|
||||
|
||||
if (save_path) {
|
||||
if ((client.fd = open(save_path, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR)) < 0) {
|
||||
if ((client->fd = open(save_path, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR)) < 0) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -2478,31 +2507,84 @@ static switch_status_t fetch_cache_data(http_file_context_t *context, const char
|
|||
switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1);
|
||||
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
if (!strncasecmp(url, "https", 5)) {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
}
|
||||
|
||||
client.max_bytes = HTTAPI_MAX_FILE_BYTES;
|
||||
client->max_bytes = HTTAPI_MAX_FILE_BYTES;
|
||||
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10);
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_URL, url);
|
||||
|
||||
if (client->profile->timeout) {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, client->profile->timeout);
|
||||
}
|
||||
|
||||
if (client->profile->ssl_cert_file) {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLCERT, client->profile->ssl_cert_file);
|
||||
}
|
||||
|
||||
if (client->profile->ssl_key_file) {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLKEY, client->profile->ssl_key_file);
|
||||
}
|
||||
|
||||
if (client->profile->ssl_key_password) {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLKEYPASSWD, client->profile->ssl_key_password);
|
||||
}
|
||||
|
||||
if (client->profile->ssl_version) {
|
||||
if (!strcasecmp(client->profile->ssl_version, "SSLv3")) {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3);
|
||||
#ifdef CURL_SSLVERSION_TLSv1_1
|
||||
} else if (!strcasecmp(client->profile->ssl_version, "TLSv1.1")) {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_1);
|
||||
#endif
|
||||
#ifdef CURL_SSLVERSION_TLSv1_2
|
||||
} else if (!strcasecmp(client->profile->ssl_version, "TLSv1.2")) {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
|
||||
}
|
||||
|
||||
if (client->profile->ssl_cacert_file) {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_CAINFO, client->profile->ssl_cacert_file);
|
||||
}
|
||||
|
||||
if (client->profile->enable_ssl_verifyhost) {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 2);
|
||||
}
|
||||
|
||||
if (client->profile->cookie_file) {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_COOKIEJAR, client->profile->cookie_file);
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_COOKIEFILE, client->profile->cookie_file);
|
||||
} else {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_COOKIE, "");
|
||||
}
|
||||
|
||||
if (client->profile->bind_local) {
|
||||
curl_easy_setopt(curl_handle, CURLOPT_INTERFACE, client->profile->bind_local);
|
||||
}
|
||||
|
||||
if (save_path) {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, save_file_callback);
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &client);
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) client);
|
||||
} else {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_HEADER, 1);
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_NOBODY, 1);
|
||||
}
|
||||
|
||||
if (headers) {
|
||||
switch_event_create(&client.headers, SWITCH_EVENT_CLONE);
|
||||
switch_event_create(&client->headers, SWITCH_EVENT_CLONE);
|
||||
if (save_path) {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, get_header_callback);
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, (void *) &client);
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, (void *) client);
|
||||
} else {
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, get_header_callback);
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &client);
|
||||
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) client);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2516,19 +2598,20 @@ static switch_status_t fetch_cache_data(http_file_context_t *context, const char
|
|||
switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &code);
|
||||
switch_curl_easy_cleanup(curl_handle);
|
||||
|
||||
if (client.fd > -1) {
|
||||
close(client.fd);
|
||||
if (client->fd > -1) {
|
||||
close(client->fd);
|
||||
}
|
||||
|
||||
if (headers && client.headers) {
|
||||
switch_event_add_header(client.headers, SWITCH_STACK_BOTTOM, "http-response-code", "%ld", code);
|
||||
*headers = client.headers;
|
||||
if (headers && client->headers) {
|
||||
switch_event_add_header(client->headers, SWITCH_STACK_BOTTOM, "http-response-code", "%ld", code);
|
||||
*headers = client->headers;
|
||||
client->headers = NULL;
|
||||
}
|
||||
|
||||
switch(code) {
|
||||
case 200:
|
||||
if (save_path) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "caching: url:%s to %s (%" SWITCH_SIZE_T_FMT " bytes)\n", url, save_path, client.bytes);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "caching: url:%s to %s (%" SWITCH_SIZE_T_FMT " bytes)\n", url, save_path, client->bytes);
|
||||
}
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
break;
|
||||
|
@ -2544,7 +2627,7 @@ static switch_status_t fetch_cache_data(http_file_context_t *context, const char
|
|||
|
||||
switch_safe_free(dynamic_url);
|
||||
switch_safe_free(dup_creds);
|
||||
|
||||
client_destroy(&client);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -2704,6 +2787,7 @@ static switch_status_t locate_url_file(http_file_context_t *context, const char
|
|||
|
||||
if (switch_file_exists(context->cache_file, context->pool) != SWITCH_STATUS_SUCCESS && unreachable) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "File at url [%s] is unreachable!\n", url);
|
||||
status = SWITCH_STATUS_NOTFOUND;
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* aws.c for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2013, Grasshopper
|
||||
* Copyright (C) 2013-2014, Grasshopper
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
|
@ -41,8 +41,18 @@
|
|||
* @param url to check
|
||||
* @return true if this is an S3 url
|
||||
*/
|
||||
int aws_s3_is_s3_url(const char *url)
|
||||
int aws_s3_is_s3_url(const char *url, const char *base_domain)
|
||||
{
|
||||
if (!zstr(base_domain)) {
|
||||
char *base_domain_escaped;
|
||||
char regex[1024];
|
||||
int result;
|
||||
base_domain_escaped = switch_string_replace(base_domain, ".", "\\.");
|
||||
switch_snprintf(regex, 1024, "^https?://\\w[-\\w.]{1,61}\\w\\.%s/.*$", base_domain_escaped);
|
||||
result = !zstr(url) && switch_regex_match(url, regex) == SWITCH_STATUS_SUCCESS;
|
||||
switch_safe_free(base_domain_escaped);
|
||||
return result;
|
||||
}
|
||||
/* AWS bucket naming rules are complex... this match only supports virtual hosting of buckets */
|
||||
return !zstr(url) && switch_regex_match(url, "^https?://\\w[-\\w.]{1,61}\\w\\.s3([-\\w]+)?\\.amazonaws\\.com/.*$") == SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -141,10 +151,11 @@ static char *my_strrstr(const char *haystack, const char *needle)
|
|||
/**
|
||||
* Parse bucket and object from URL
|
||||
* @param url to parse. This value is modified.
|
||||
* @param base_domain of URL (assumes s3.amazonaws.com if not specified)
|
||||
* @param bucket to store result in
|
||||
* @param bucket_length of result buffer
|
||||
*/
|
||||
void aws_s3_parse_url(char *url, char **bucket, char **object)
|
||||
void aws_s3_parse_url(char *url, const char *base_domain, char **bucket, char **object)
|
||||
{
|
||||
char *bucket_start = NULL;
|
||||
char *bucket_end;
|
||||
|
@ -153,7 +164,7 @@ void aws_s3_parse_url(char *url, char **bucket, char **object)
|
|||
*bucket = NULL;
|
||||
*object = NULL;
|
||||
|
||||
if (!aws_s3_is_s3_url(url)) {
|
||||
if (!aws_s3_is_s3_url(url, base_domain)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -167,8 +178,15 @@ void aws_s3_parse_url(char *url, char **bucket, char **object)
|
|||
/* invalid URL */
|
||||
return;
|
||||
}
|
||||
|
||||
bucket_end = my_strrstr(bucket_start, ".s3");
|
||||
|
||||
{
|
||||
char base_domain_match[1024];
|
||||
if (zstr(base_domain)) {
|
||||
base_domain = "s3";
|
||||
}
|
||||
switch_snprintf(base_domain_match, 1024, ".%s", base_domain);
|
||||
bucket_end = my_strrstr(bucket_start, base_domain_match);
|
||||
}
|
||||
if (!bucket_end) {
|
||||
/* invalid URL */
|
||||
return;
|
||||
|
@ -195,6 +213,7 @@ void aws_s3_parse_url(char *url, char **bucket, char **object)
|
|||
* Create a pre-signed URL for AWS S3
|
||||
* @param verb (PUT/GET)
|
||||
* @param url address (virtual-host-style)
|
||||
* @param base_domain (optional - amazon aws assumed if not specified)
|
||||
* @param content_type optional content type
|
||||
* @param content_md5 optional content MD5 checksum
|
||||
* @param aws_access_key_id secret access key identifier
|
||||
|
@ -202,7 +221,7 @@ void aws_s3_parse_url(char *url, char **bucket, char **object)
|
|||
* @param expires seconds since the epoch
|
||||
* @return presigned_url
|
||||
*/
|
||||
char *aws_s3_presigned_url_create(const char *verb, const char *url, const char *content_type, const char *content_md5, const char *aws_access_key_id, const char *aws_secret_access_key, const char *expires)
|
||||
char *aws_s3_presigned_url_create(const char *verb, const char *url, const char *base_domain, const char *content_type, const char *content_md5, const char *aws_access_key_id, const char *aws_secret_access_key, const char *expires)
|
||||
{
|
||||
char signature[S3_SIGNATURE_LENGTH_MAX];
|
||||
char signature_url_encoded[S3_SIGNATURE_LENGTH_MAX];
|
||||
|
@ -212,7 +231,7 @@ char *aws_s3_presigned_url_create(const char *verb, const char *url, const char
|
|||
char *object;
|
||||
|
||||
/* create URL encoded signature */
|
||||
aws_s3_parse_url(url_dup, &bucket, &object);
|
||||
aws_s3_parse_url(url_dup, base_domain, &bucket, &object);
|
||||
string_to_sign = aws_s3_string_to_sign(verb, bucket, object, content_type, content_md5, expires);
|
||||
signature[0] = '\0';
|
||||
aws_s3_signature(signature, S3_SIGNATURE_LENGTH_MAX, string_to_sign, aws_secret_access_key);
|
||||
|
@ -230,6 +249,7 @@ char *aws_s3_presigned_url_create(const char *verb, const char *url, const char
|
|||
* @param authentication_length maximum result length
|
||||
* @param verb (PUT/GET)
|
||||
* @param url address (virtual-host-style)
|
||||
* @param base_domain (optional - amazon aws assumed if not specified)
|
||||
* @param content_type optional content type
|
||||
* @param content_md5 optional content MD5 checksum
|
||||
* @param aws_access_key_id secret access key identifier
|
||||
|
@ -237,7 +257,7 @@ char *aws_s3_presigned_url_create(const char *verb, const char *url, const char
|
|||
* @param date header
|
||||
* @return signature for Authorization header
|
||||
*/
|
||||
char *aws_s3_authentication_create(const char *verb, const char *url, const char *content_type, const char *content_md5, const char *aws_access_key_id, const char *aws_secret_access_key, const char *date)
|
||||
char *aws_s3_authentication_create(const char *verb, const char *url, const char *base_domain, const char *content_type, const char *content_md5, const char *aws_access_key_id, const char *aws_secret_access_key, const char *date)
|
||||
{
|
||||
char signature[S3_SIGNATURE_LENGTH_MAX];
|
||||
char *string_to_sign;
|
||||
|
@ -246,7 +266,7 @@ char *aws_s3_authentication_create(const char *verb, const char *url, const char
|
|||
char *object;
|
||||
|
||||
/* create base64 encoded signature */
|
||||
aws_s3_parse_url(url_dup, &bucket, &object);
|
||||
aws_s3_parse_url(url_dup, base_domain, &bucket, &object);
|
||||
string_to_sign = aws_s3_string_to_sign(verb, bucket, object, content_type, content_md5, date);
|
||||
signature[0] = '\0';
|
||||
aws_s3_signature(signature, S3_SIGNATURE_LENGTH_MAX, string_to_sign, aws_secret_access_key);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* aws.h for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2013, Grasshopper
|
||||
* Copyright (C) 2013-2014, Grasshopper
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
|
@ -34,12 +34,12 @@
|
|||
/* (SHA1_LENGTH * 1.37 base64 bytes per byte * 3 url-encoded bytes per byte) */
|
||||
#define S3_SIGNATURE_LENGTH_MAX 83
|
||||
|
||||
int aws_s3_is_s3_url(const char *url);
|
||||
void aws_s3_parse_url(char *url, char **bucket, char **object);
|
||||
int aws_s3_is_s3_url(const char *url, const char *base_domain);
|
||||
void aws_s3_parse_url(char *url, const char *base_domain, char **bucket, char **object);
|
||||
char *aws_s3_string_to_sign(const char *verb, const char *bucket, const char *object, const char *content_type, const char *content_md5, const char *date);
|
||||
char *aws_s3_signature(char *signature, int signature_length, const char *string_to_sign, const char *aws_secret_access_key);
|
||||
char *aws_s3_presigned_url_create(const char *verb, const char *url, const char *content_type, const char *content_md5, const char *aws_access_key_id, const char *aws_secret_access_key, const char *expires);
|
||||
char *aws_s3_authentication_create(const char *verb, const char *url, const char *content_type, const char *content_md5, const char *aws_access_key_id, const char *aws_secret_access_key, const char *date);
|
||||
char *aws_s3_presigned_url_create(const char *verb, const char *url, const char *base_domain, const char *content_type, const char *content_md5, const char *aws_access_key_id, const char *aws_secret_access_key, const char *expires);
|
||||
char *aws_s3_authentication_create(const char *verb, const char *url, const char *base_domain, const char *content_type, const char *content_md5, const char *aws_access_key_id, const char *aws_secret_access_key, const char *date);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
<access-key-id><![CDATA[AKIAIOSFODNN7EXAMPLE]]></access-key-id>
|
||||
<!-- 40 character secret -->
|
||||
<secret-access-key><![CDATA[wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY]]></secret-access-key>
|
||||
<!--base-url><![CDATA[s3.example.com]]></base-url-->
|
||||
</aws-s3>
|
||||
<!-- Domains that this profile applies to -->
|
||||
<domains>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2005-2013, Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
|
@ -61,6 +61,7 @@ struct http_profile {
|
|||
const char *name;
|
||||
const char *aws_s3_access_key_id;
|
||||
const char *aws_s3_secret_access_key;
|
||||
const char *aws_s3_base_domain;
|
||||
};
|
||||
typedef struct http_profile http_profile_t;
|
||||
|
||||
|
@ -201,7 +202,7 @@ static void url_cache_unlock(url_cache_t *cache, switch_core_session_t *session)
|
|||
static void url_cache_clear(url_cache_t *cache, switch_core_session_t *session);
|
||||
static http_profile_t *url_cache_http_profile_find(url_cache_t *cache, const char *name);
|
||||
static http_profile_t *url_cache_http_profile_find_by_fqdn(url_cache_t *cache, const char *url);
|
||||
static http_profile_t *url_cache_http_profile_add(url_cache_t *cache, const char *name, const char *aws_s3_access_key_id, const char *aws_s3_secret_access_key);
|
||||
static http_profile_t *url_cache_http_profile_add(url_cache_t *cache, const char *name, const char *aws_s3_access_key_id, const char *aws_s3_secret_access_key, const char *aws_s3_base_domain);
|
||||
|
||||
static switch_curl_slist_t *append_aws_s3_headers(switch_curl_slist_t *headers, http_profile_t *profile, const char *verb, const char *content_type, const char *url);
|
||||
|
||||
|
@ -792,7 +793,7 @@ static http_profile_t *url_cache_http_profile_find_by_fqdn(url_cache_t *cache, c
|
|||
/**
|
||||
* Add a profile to the cache
|
||||
*/
|
||||
static http_profile_t *url_cache_http_profile_add(url_cache_t *cache, const char *name, const char *aws_s3_access_key_id, const char *aws_s3_secret_access_key)
|
||||
static http_profile_t *url_cache_http_profile_add(url_cache_t *cache, const char *name, const char *aws_s3_access_key_id, const char *aws_s3_secret_access_key, const char *aws_s3_base_domain)
|
||||
{
|
||||
http_profile_t *profile = switch_core_alloc(cache->pool, sizeof(*profile));
|
||||
profile->name = switch_core_strdup(cache->pool, name);
|
||||
|
@ -802,6 +803,10 @@ static http_profile_t *url_cache_http_profile_add(url_cache_t *cache, const char
|
|||
if (aws_s3_secret_access_key) {
|
||||
profile->aws_s3_secret_access_key = switch_core_strdup(cache->pool, aws_s3_secret_access_key);
|
||||
}
|
||||
if (aws_s3_base_domain) {
|
||||
profile->aws_s3_base_domain = switch_core_strdup(cache->pool, aws_s3_base_domain);
|
||||
}
|
||||
|
||||
switch_core_hash_insert(cache->profiles, profile->name, profile);
|
||||
return profile;
|
||||
}
|
||||
|
@ -919,7 +924,7 @@ static void cached_url_destroy(cached_url_t *url, switch_memory_pool_t *pool)
|
|||
static switch_curl_slist_t *append_aws_s3_headers(switch_curl_slist_t *headers, http_profile_t *profile, const char *verb, const char *content_type, const char *url)
|
||||
{
|
||||
/* check if Amazon headers are needed */
|
||||
if (profile && profile->aws_s3_access_key_id && aws_s3_is_s3_url(url)) {
|
||||
if (profile && profile->aws_s3_access_key_id && aws_s3_is_s3_url(url, profile->aws_s3_base_domain)) {
|
||||
char date[256];
|
||||
char header[1024];
|
||||
char *authenticate;
|
||||
|
@ -930,7 +935,7 @@ static switch_curl_slist_t *append_aws_s3_headers(switch_curl_slist_t *headers,
|
|||
headers = switch_curl_slist_append(headers, header);
|
||||
|
||||
/* Authorization: */
|
||||
authenticate = aws_s3_authentication_create(verb, url, content_type, "", profile->aws_s3_access_key_id, profile->aws_s3_secret_access_key, date);
|
||||
authenticate = aws_s3_authentication_create(verb, url, profile->aws_s3_base_domain, content_type, "", profile->aws_s3_access_key_id, profile->aws_s3_secret_access_key, date);
|
||||
snprintf(header, 1024, "Authorization: %s", authenticate);
|
||||
free(authenticate);
|
||||
headers = switch_curl_slist_append(headers, header);
|
||||
|
@ -1397,7 +1402,9 @@ static switch_status_t do_config(url_cache_t *cache)
|
|||
switch_xml_t s3 = switch_xml_child(profile, "aws-s3");
|
||||
char *access_key_id = NULL;
|
||||
char *secret_access_key = NULL;
|
||||
char *base_domain = NULL;
|
||||
if (s3) {
|
||||
switch_xml_t base_domain_xml = switch_xml_child(s3, "base-domain");
|
||||
switch_xml_t id = switch_xml_child(s3, "access-key-id");
|
||||
switch_xml_t secret = switch_xml_child(s3, "secret-access-key");
|
||||
if (id && secret) {
|
||||
|
@ -1412,12 +1419,21 @@ static switch_status_t do_config(url_cache_t *cache)
|
|||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing key id or secret\n");
|
||||
continue;
|
||||
}
|
||||
if (base_domain_xml) {
|
||||
base_domain = switch_strip_whitespace(switch_xml_txt(base_domain_xml));
|
||||
if (zstr(base_domain)) {
|
||||
switch_safe_free(base_domain);
|
||||
base_domain = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Adding profile \"%s\" to cache\n", name);
|
||||
profile_obj = url_cache_http_profile_add(cache, name, access_key_id, secret_access_key);
|
||||
profile_obj = url_cache_http_profile_add(cache, name, access_key_id, secret_access_key, base_domain);
|
||||
switch_safe_free(access_key_id);
|
||||
switch_safe_free(secret_access_key);
|
||||
switch_safe_free(base_domain);
|
||||
|
||||
domains = switch_xml_child(profile, "domains");
|
||||
if (domains) {
|
||||
|
|
|
@ -41,24 +41,28 @@ static void test_signature(void)
|
|||
*/
|
||||
static void test_check_url(void)
|
||||
{
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("http://bucket.s3-us-west-1.amazonaws.com/object.ext"));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("https://bucket.s3-us-west-1.amazonaws.com/object.ext"));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("http://bucket.s3.amazonaws.com/object.ext"));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("http://bucket.s3.amazonaws.com/object.ext"));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("http://bucket.s3.amazonaws.com/object"));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("http://red.bucket.s3.amazonaws.com/object.ext"));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("https://bucket.s3.amazonaws.com/object.ext"));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("https://bucket.s3.amazonaws.com/object"));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("https://bucket.s3.amazonaws.com/recordings/1240fwjf8we.mp3"));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("https://bucket.s3.amazonaws.com/en/us/8000/1232345.mp3"));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("https://bucket_with_underscore.s3.amazonaws.com/en/us/8000/1232345.mp3"));
|
||||
ASSERT_FALSE(aws_s3_is_s3_url("bucket.s3.amazonaws.com/object.ext"));
|
||||
ASSERT_FALSE(aws_s3_is_s3_url("https://s3.amazonaws.com/bucket/object"));
|
||||
ASSERT_FALSE(aws_s3_is_s3_url("http://s3.amazonaws.com/bucket/object"));
|
||||
ASSERT_FALSE(aws_s3_is_s3_url("http://google.com/"));
|
||||
ASSERT_FALSE(aws_s3_is_s3_url("http://phono.com/audio/troporocks.mp3"));
|
||||
ASSERT_FALSE(aws_s3_is_s3_url(""));
|
||||
ASSERT_FALSE(aws_s3_is_s3_url(NULL));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("http://bucket.s3-us-west-1.amazonaws.com/object.ext", NULL));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("https://bucket.s3-us-west-1.amazonaws.com/object.ext", NULL));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("http://bucket.s3.amazonaws.com/object.ext", NULL));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("http://bucket.s3.amazonaws.com/object.ext", NULL));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("http://bucket.s3.amazonaws.com/object", NULL));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("http://red.bucket.s3.amazonaws.com/object.ext", NULL));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("https://bucket.s3.amazonaws.com/object.ext", NULL));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("https://bucket.s3.amazonaws.com/object", NULL));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("https://bucket.s3.amazonaws.com/recordings/1240fwjf8we.mp3", NULL));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("https://bucket.s3.amazonaws.com/en/us/8000/1232345.mp3", NULL));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("https://bucket_with_underscore.s3.amazonaws.com/en/us/8000/1232345.mp3", NULL));
|
||||
ASSERT_FALSE(aws_s3_is_s3_url("bucket.s3.amazonaws.com/object.ext", NULL));
|
||||
ASSERT_FALSE(aws_s3_is_s3_url("https://s3.amazonaws.com/bucket/object", NULL));
|
||||
ASSERT_FALSE(aws_s3_is_s3_url("http://s3.amazonaws.com/bucket/object", NULL));
|
||||
ASSERT_FALSE(aws_s3_is_s3_url("http://google.com/", NULL));
|
||||
ASSERT_FALSE(aws_s3_is_s3_url("http://phono.com/audio/troporocks.mp3", NULL));
|
||||
ASSERT_FALSE(aws_s3_is_s3_url("", NULL));
|
||||
ASSERT_FALSE(aws_s3_is_s3_url(NULL, NULL));
|
||||
ASSERT_FALSE(aws_s3_is_s3_url("https://example.com/bucket/object", "example.com"));
|
||||
ASSERT_TRUE(aws_s3_is_s3_url("http://bucket.example.com/object", "example.com"));
|
||||
ASSERT_FALSE(aws_s3_is_s3_url("", "example.com"));
|
||||
ASSERT_FALSE(aws_s3_is_s3_url(NULL, "example.com"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,51 +72,55 @@ static void test_parse_url(void)
|
|||
{
|
||||
char *bucket;
|
||||
char *object;
|
||||
aws_s3_parse_url(strdup("http://quotes.s3.amazonaws.com/nelson"), &bucket, &object);
|
||||
aws_s3_parse_url(strdup("http://quotes.s3.amazonaws.com/nelson"), NULL, &bucket, &object);
|
||||
ASSERT_STRING_EQUALS("quotes", bucket);
|
||||
ASSERT_STRING_EQUALS("nelson", object);
|
||||
|
||||
aws_s3_parse_url(strdup("https://quotes.s3.amazonaws.com/nelson.mp3"), &bucket, &object);
|
||||
aws_s3_parse_url(strdup("https://quotes.s3.amazonaws.com/nelson.mp3"), NULL, &bucket, &object);
|
||||
ASSERT_STRING_EQUALS("quotes", bucket);
|
||||
ASSERT_STRING_EQUALS("nelson.mp3", object);
|
||||
|
||||
aws_s3_parse_url(strdup("http://s3.amazonaws.com/quotes/nelson"), &bucket, &object);
|
||||
aws_s3_parse_url(strdup("http://s3.amazonaws.com/quotes/nelson"), NULL, &bucket, &object);
|
||||
ASSERT_NULL(bucket);
|
||||
ASSERT_NULL(object);
|
||||
|
||||
aws_s3_parse_url(strdup("http://quotes/quotes/nelson"), &bucket, &object);
|
||||
aws_s3_parse_url(strdup("http://quotes/quotes/nelson"), NULL, &bucket, &object);
|
||||
ASSERT_NULL(bucket);
|
||||
ASSERT_NULL(object);
|
||||
|
||||
aws_s3_parse_url(strdup("http://quotes.s3.amazonaws.com/"), &bucket, &object);
|
||||
aws_s3_parse_url(strdup("http://quotes.s3.amazonaws.com/"), NULL, &bucket, &object);
|
||||
ASSERT_NULL(bucket);
|
||||
ASSERT_NULL(object);
|
||||
|
||||
aws_s3_parse_url(strdup("http://quotes.s3.amazonaws.com"), &bucket, &object);
|
||||
aws_s3_parse_url(strdup("http://quotes.s3.amazonaws.com"), NULL, &bucket, &object);
|
||||
ASSERT_NULL(bucket);
|
||||
ASSERT_NULL(object);
|
||||
|
||||
aws_s3_parse_url(strdup("http://quotes"), &bucket, &object);
|
||||
aws_s3_parse_url(strdup("http://quotes"), NULL, &bucket, &object);
|
||||
ASSERT_NULL(bucket);
|
||||
ASSERT_NULL(object);
|
||||
|
||||
aws_s3_parse_url(strdup(""), &bucket, &object);
|
||||
aws_s3_parse_url(strdup(""), NULL, &bucket, &object);
|
||||
ASSERT_NULL(bucket);
|
||||
ASSERT_NULL(object);
|
||||
|
||||
aws_s3_parse_url(NULL, &bucket, &object);
|
||||
aws_s3_parse_url(NULL, NULL, &bucket, &object);
|
||||
ASSERT_NULL(bucket);
|
||||
ASSERT_NULL(object);
|
||||
|
||||
aws_s3_parse_url(strdup("http://bucket.s3.amazonaws.com/voicemails/recording.wav"), &bucket, &object);
|
||||
aws_s3_parse_url(strdup("http://bucket.s3.amazonaws.com/voicemails/recording.wav"), NULL, &bucket, &object);
|
||||
ASSERT_STRING_EQUALS("bucket", bucket);
|
||||
ASSERT_STRING_EQUALS("voicemails/recording.wav", object);
|
||||
|
||||
aws_s3_parse_url(strdup("https://my-bucket-with-dash.s3-us-west-2.amazonaws.com/greeting/file/1002/Lumino.mp3"), &bucket, &object);
|
||||
aws_s3_parse_url(strdup("https://my-bucket-with-dash.s3-us-west-2.amazonaws.com/greeting/file/1002/Lumino.mp3"), NULL, &bucket, &object);
|
||||
ASSERT_STRING_EQUALS("my-bucket-with-dash", bucket);
|
||||
ASSERT_STRING_EQUALS("greeting/file/1002/Lumino.mp3", object);
|
||||
|
||||
aws_s3_parse_url(strdup("http://quotes.s3.foo.bar.s3.amazonaws.com/greeting/file/1002/Lumino.mp3"), &bucket, &object);
|
||||
aws_s3_parse_url(strdup("http://quotes.s3.foo.bar.s3.amazonaws.com/greeting/file/1002/Lumino.mp3"), NULL, &bucket, &object);
|
||||
ASSERT_STRING_EQUALS("quotes.s3.foo.bar", bucket);
|
||||
ASSERT_STRING_EQUALS("greeting/file/1002/Lumino.mp3", object);
|
||||
|
||||
aws_s3_parse_url(strdup("http://quotes.s3.foo.bar.example.com/greeting/file/1002/Lumino.mp3"), "example.com", &bucket, &object);
|
||||
ASSERT_STRING_EQUALS("quotes.s3.foo.bar", bucket);
|
||||
ASSERT_STRING_EQUALS("greeting/file/1002/Lumino.mp3", object);
|
||||
}
|
||||
|
@ -122,7 +130,9 @@ static void test_parse_url(void)
|
|||
*/
|
||||
static void test_authorization_header(void)
|
||||
{
|
||||
ASSERT_STRING_EQUALS("AWS AKIAIOSFODNN7EXAMPLE:YJkomOaqUJlvEluDq4fpusID38Y=", aws_s3_authentication_create("GET", "https://vault.s3.amazonaws.com/awesome.mp3", "audio/mpeg", "", "AKIAIOSFODNN7EXAMPLE", "0123456789012345678901234567890123456789", "1234567890"));
|
||||
ASSERT_STRING_EQUALS("AWS AKIAIOSFODNN7EXAMPLE:YJkomOaqUJlvEluDq4fpusID38Y=", aws_s3_authentication_create("GET", "https://vault.s3.amazonaws.com/awesome.mp3", NULL, "audio/mpeg", "", "AKIAIOSFODNN7EXAMPLE", "0123456789012345678901234567890123456789", "1234567890"));
|
||||
ASSERT_STRING_EQUALS("AWS AKIAIOSFODNN7EXAMPLE:YJkomOaqUJlvEluDq4fpusID38Y=", aws_s3_authentication_create("GET", "https://vault.s3.amazonaws.com/awesome.mp3", "s3.amazonaws.com", "audio/mpeg", "", "AKIAIOSFODNN7EXAMPLE", "0123456789012345678901234567890123456789", "1234567890"));
|
||||
ASSERT_STRING_EQUALS("AWS AKIAIOSFODNN7EXAMPLE:YJkomOaqUJlvEluDq4fpusID38Y=", aws_s3_authentication_create("GET", "https://vault.example.com/awesome.mp3", "example.com", "audio/mpeg", "", "AKIAIOSFODNN7EXAMPLE", "0123456789012345678901234567890123456789", "1234567890"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -130,7 +140,9 @@ static void test_authorization_header(void)
|
|||
*/
|
||||
static void test_presigned_url(void)
|
||||
{
|
||||
ASSERT_STRING_EQUALS("https://vault.s3.amazonaws.com/awesome.mp3?Signature=YJkomOaqUJlvEluDq4fpusID38Y%3D&Expires=1234567890&AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE", aws_s3_presigned_url_create("GET", "https://vault.s3.amazonaws.com/awesome.mp3", "audio/mpeg", "", "AKIAIOSFODNN7EXAMPLE", "0123456789012345678901234567890123456789", "1234567890"));
|
||||
ASSERT_STRING_EQUALS("https://vault.s3.amazonaws.com/awesome.mp3?Signature=YJkomOaqUJlvEluDq4fpusID38Y%3D&Expires=1234567890&AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE", aws_s3_presigned_url_create("GET", "https://vault.s3.amazonaws.com/awesome.mp3", NULL, "audio/mpeg", "", "AKIAIOSFODNN7EXAMPLE", "0123456789012345678901234567890123456789", "1234567890"));
|
||||
ASSERT_STRING_EQUALS("https://vault.s3.amazonaws.com/awesome.mp3?Signature=YJkomOaqUJlvEluDq4fpusID38Y%3D&Expires=1234567890&AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE", aws_s3_presigned_url_create("GET", "https://vault.s3.amazonaws.com/awesome.mp3", "s3.amazonaws.com", "audio/mpeg", "", "AKIAIOSFODNN7EXAMPLE", "0123456789012345678901234567890123456789", "1234567890"));
|
||||
ASSERT_STRING_EQUALS("https://vault.example.com/awesome.mp3?Signature=YJkomOaqUJlvEluDq4fpusID38Y%3D&Expires=1234567890&AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE", aws_s3_presigned_url_create("GET", "https://vault.example.com/awesome.mp3", "example.com", "audio/mpeg", "", "AKIAIOSFODNN7EXAMPLE", "0123456789012345678901234567890123456789", "1234567890"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,6 +40,7 @@ static struct{
|
|||
char *host;
|
||||
int port;
|
||||
int timeout;
|
||||
switch_bool_t ignore_connect_fail;
|
||||
} globals;
|
||||
|
||||
static switch_xml_config_item_t instructions[] = {
|
||||
|
@ -47,6 +48,7 @@ static switch_xml_config_item_t instructions[] = {
|
|||
SWITCH_CONFIG_ITEM_STRING_STRDUP("host", CONFIG_RELOAD, &globals.host, NULL, "localhost", "Hostname for redis server"),
|
||||
SWITCH_CONFIG_ITEM("port", SWITCH_CONFIG_INT, CONFIG_RELOADABLE, &globals.port, (void *) 6379, NULL,NULL, NULL),
|
||||
SWITCH_CONFIG_ITEM("timeout", SWITCH_CONFIG_INT, CONFIG_RELOADABLE, &globals.timeout, (void *) 10000, NULL,NULL, NULL),
|
||||
SWITCH_CONFIG_ITEM("ignore_connect_fail", SWITCH_CONFIG_BOOL, CONFIG_RELOADABLE, &globals.ignore_connect_fail, SWITCH_FALSE, NULL, "true|false", "Set to true in order to continue when redis is not contactable"),
|
||||
SWITCH_CONFIG_ITEM_END()
|
||||
};
|
||||
|
||||
|
@ -85,9 +87,14 @@ SWITCH_LIMIT_INCR(limit_incr_redis)
|
|||
REDIS redis;
|
||||
|
||||
if (redis_factory(&redis) != SWITCH_STATUS_SUCCESS) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
if ( globals.ignore_connect_fail ) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignore_connect_fail=true, so ignoring the fact that redis was not contactabl and continuing with the call\n" );
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
} else {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Get the keys for redis server */
|
||||
uuid_rediskey = switch_core_session_sprintf(session,"%s_%s_%s", switch_core_get_switchname(), realm, resource);
|
||||
rediskey = switch_core_session_sprintf(session, "%s_%s", realm, resource);
|
||||
|
@ -163,7 +170,13 @@ SWITCH_LIMIT_RELEASE(limit_release_redis)
|
|||
}
|
||||
|
||||
if (redis_factory(&redis) != SWITCH_STATUS_SUCCESS) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
if ( globals.ignore_connect_fail ) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignore_connect_fail=true, so ignoring the fact that redis was not contactabl and continuing with the call\n" );
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
} else {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
switch_mutex_lock(pvt->mutex);
|
||||
|
|
|
@ -522,6 +522,25 @@ SWITCH_STANDARD_CHAT_APP(set_function)
|
|||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_CHAT_APP(unset_function)
|
||||
{
|
||||
char *var;
|
||||
|
||||
if (!data) return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
var = strdup(data);
|
||||
|
||||
if (!var) return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
if (!zstr(var)) {
|
||||
switch_event_del_header(message, var);
|
||||
}
|
||||
|
||||
free(var);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_CHAT_APP(fire_function)
|
||||
{
|
||||
switch_event_t *fireme;
|
||||
|
@ -573,6 +592,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sms_load)
|
|||
SWITCH_ADD_CHAT_APP(chat_app_interface, "reply", "reply to a message", "reply to a message", reply_function, "", SCAF_NONE);
|
||||
SWITCH_ADD_CHAT_APP(chat_app_interface, "stop", "stop execution", "stop execution", stop_function, "", SCAF_NONE);
|
||||
SWITCH_ADD_CHAT_APP(chat_app_interface, "set", "set a variable", "set a variable", set_function, "", SCAF_NONE);
|
||||
SWITCH_ADD_CHAT_APP(chat_app_interface, "unset", "unset a variable", "unset a variable", unset_function, "", SCAF_NONE);
|
||||
SWITCH_ADD_CHAT_APP(chat_app_interface, "send", "send the message as-is", "send the message as-is", send_function, "", SCAF_NONE);
|
||||
SWITCH_ADD_CHAT_APP(chat_app_interface, "fire", "fire the message", "fire the message", fire_function, "", SCAF_NONE);
|
||||
SWITCH_ADD_CHAT_APP(chat_app_interface, "system", "execute a system command", "execute a sytem command", system_function, "", SCAF_NONE);
|
||||
|
|
|
@ -788,12 +788,12 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_spandsp_init)
|
|||
if (mod_spandsp_dsp_load(module_interface, pool) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't load or process spandsp.conf, not adding tone_detect applications\n");
|
||||
} else {
|
||||
SWITCH_ADD_APP(app_interface, "start_tone_detect", "Start background tone detection with cadence", "", start_tone_detect_app, "<name>", SAF_NONE);
|
||||
SWITCH_ADD_APP(app_interface, "stop_tone_detect", "Stop background tone detection with cadence", "", stop_tone_detect_app, "", SAF_NONE);
|
||||
SWITCH_ADD_API(api_interface, "start_tone_detect", "Start background tone detection with cadence", start_tone_detect_api, "<uuid> <name>");
|
||||
SWITCH_ADD_API(api_interface, "stop_tone_detect", "Stop background tone detection with cadence", stop_tone_detect_api, "<uuid>");
|
||||
switch_console_set_complete("add start_tone_detect ::console::list_uuid");
|
||||
switch_console_set_complete("add stop_tone_detect ::console::list_uuid");
|
||||
SWITCH_ADD_APP(app_interface, "spandsp_start_tone_detect", "Start background tone detection with cadence", "", start_tone_detect_app, "<name>", SAF_NONE);
|
||||
SWITCH_ADD_APP(app_interface, "spandsp_stop_tone_detect", "Stop background tone detection with cadence", "", stop_tone_detect_app, "", SAF_NONE);
|
||||
SWITCH_ADD_API(api_interface, "spandsp_start_tone_detect", "Start background tone detection with cadence", start_tone_detect_api, "<uuid> <name>");
|
||||
SWITCH_ADD_API(api_interface, "spandsp_stop_tone_detect", "Stop background tone detection with cadence", stop_tone_detect_api, "<uuid>");
|
||||
switch_console_set_complete("add spandsp_start_tone_detect ::console::list_uuid");
|
||||
switch_console_set_complete("add spandsp_stop_tone_detect ::console::list_uuid");
|
||||
}
|
||||
|
||||
SWITCH_ADD_API(api_interface, "start_tdd_detect", "Start background tdd detection", start_tdd_detect_api, "<uuid>");
|
||||
|
|
|
@ -76,6 +76,10 @@
|
|||
//#define WEBRTC_ARCH_ARMEL
|
||||
#define WEBRTC_ARCH_32_BITS
|
||||
#define WEBRTC_ARCH_LITTLE_ENDIAN
|
||||
#elif defined(__MIPSEB__)
|
||||
#define WEBRTC_ARCH_BIG_ENDIAN
|
||||
#elif defined(__MIPSEL__)
|
||||
#define WEBRTC_ARCH_LITTLE_ENDIAN
|
||||
#else
|
||||
#error Please add support for your architecture in typedefs.h
|
||||
#endif
|
||||
|
|
|
@ -42,6 +42,7 @@ struct opus_codec_settings {
|
|||
int useinbandfec;
|
||||
int usedtx;
|
||||
int maxaveragebitrate;
|
||||
int maxplaybackrate;
|
||||
int stereo;
|
||||
int cbr;
|
||||
int sprop_maxcapturerate;
|
||||
|
@ -57,6 +58,7 @@ static opus_codec_settings_t default_codec_settings = {
|
|||
/*.useinbandfec */ 1,
|
||||
/*.usedtx */ 1,
|
||||
/*.maxaveragebitrate */ 30000,
|
||||
/*.maxplaybackrate */ 48000,
|
||||
/*.stereo*/ 0,
|
||||
/*.cbr*/ 0,
|
||||
/*.sprop_maxcapturerate*/ 0,
|
||||
|
@ -76,6 +78,8 @@ struct opus_context {
|
|||
struct {
|
||||
int use_vbr;
|
||||
int complexity;
|
||||
int maxaveragebitrate;
|
||||
int maxplaybackrate;
|
||||
switch_mutex_t *mutex;
|
||||
} opus_prefs;
|
||||
|
||||
|
@ -151,52 +155,23 @@ static switch_status_t switch_opus_fmtp_parse(const char *fmtp, switch_codec_fmt
|
|||
|
||||
if (!strcasecmp(data, "maxaveragebitrate")) {
|
||||
codec_settings->maxaveragebitrate = atoi(arg);
|
||||
switch(codec_fmtp->actual_samples_per_second) {
|
||||
case 8000:
|
||||
{
|
||||
if(codec_settings->maxaveragebitrate < 6000 || codec_settings->maxaveragebitrate > 20000) {
|
||||
codec_settings->maxaveragebitrate = 20000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 12000:
|
||||
{
|
||||
if(codec_settings->maxaveragebitrate < 7000 || codec_settings->maxaveragebitrate > 25000) {
|
||||
codec_settings->maxaveragebitrate = 25000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 16000:
|
||||
{
|
||||
if(codec_settings->maxaveragebitrate < 8000 || codec_settings->maxaveragebitrate > 30000) {
|
||||
codec_settings->maxaveragebitrate = 30000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 24000:
|
||||
{
|
||||
if(codec_settings->maxaveragebitrate < 12000 || codec_settings->maxaveragebitrate > 40000) {
|
||||
codec_settings->maxaveragebitrate = 40000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
/* this should never happen but 20000 is common among all rates */
|
||||
codec_settings->maxaveragebitrate = 20000;
|
||||
break;
|
||||
if ( codec_settings->maxaveragebitrate < 6000 || codec_settings->maxaveragebitrate > 510000 ) {
|
||||
codec_settings->maxaveragebitrate = 0; /* values outside the range between 6000 and 510000 SHOULD be ignored */
|
||||
}
|
||||
|
||||
|
||||
codec_fmtp->bits_per_second = codec_settings->maxaveragebitrate;
|
||||
}
|
||||
|
||||
if (!strcasecmp(data, "maxplaybackrate")) {
|
||||
codec_settings->maxplaybackrate = atoi(arg);
|
||||
if ( codec_settings->maxplaybackrate != 8000 && codec_settings->maxplaybackrate != 12000 && codec_settings->maxplaybackrate != 16000
|
||||
&& codec_settings->maxplaybackrate != 24000 && codec_settings->maxplaybackrate != 48000) {
|
||||
codec_settings->maxplaybackrate = 0; /* value not supported */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free(fmtp_dup);
|
||||
}
|
||||
//codec_fmtp->bits_per_second = bit_rate;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
return SWITCH_STATUS_FALSE;
|
||||
|
@ -216,7 +191,10 @@ static char *gen_fmtp(opus_codec_settings_t *settings, switch_memory_pool_t *poo
|
|||
|
||||
if (settings->maxaveragebitrate) {
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "maxaveragebitrate=%d; ", settings->maxaveragebitrate);
|
||||
|
||||
}
|
||||
|
||||
if (settings->maxplaybackrate) {
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "maxplaybackrate=%d; ", settings->maxplaybackrate);
|
||||
}
|
||||
|
||||
if (settings->ptime) {
|
||||
|
@ -264,6 +242,15 @@ static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag
|
|||
memset(&codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
|
||||
codec_fmtp.private_info = &opus_codec_settings;
|
||||
switch_opus_fmtp_parse(codec->fmtp_in, &codec_fmtp);
|
||||
|
||||
/* Verify if the local or remote configuration are lowering maxaveragebitrate and/or maxplaybackrate */
|
||||
if ( opus_prefs.maxaveragebitrate && (opus_prefs.maxaveragebitrate < opus_codec_settings.maxaveragebitrate || !opus_codec_settings.maxaveragebitrate) ) {
|
||||
opus_codec_settings.maxaveragebitrate = opus_prefs.maxaveragebitrate;
|
||||
}
|
||||
if ( opus_prefs.maxplaybackrate && (opus_prefs.maxplaybackrate < opus_codec_settings.maxplaybackrate || !opus_codec_settings.maxplaybackrate) ) {
|
||||
opus_codec_settings.maxplaybackrate = opus_prefs.maxplaybackrate;
|
||||
}
|
||||
|
||||
codec->fmtp_out = gen_fmtp(&opus_codec_settings, codec->memory_pool);
|
||||
|
||||
if (encoding) {
|
||||
|
@ -283,15 +270,39 @@ static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag
|
|||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
opus_encoder_ctl(context->encoder_object, OPUS_SET_BITRATE(bitrate_bps));
|
||||
|
||||
if (codec->implementation->actual_samples_per_second == 8000) {
|
||||
opus_encoder_ctl(context->encoder_object, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
|
||||
opus_encoder_ctl(context->encoder_object, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
|
||||
|
||||
/* Setting documented in "RTP Payload Format for Opus Speech and Audio Codec" draft-spittka-payload-rtp-opus-03 */
|
||||
if( opus_codec_settings.maxaveragebitrate ) { /* Remote codec settings found in SDP "fmtp", we accept to tune the Encoder */
|
||||
opus_encoder_ctl(context->encoder_object, OPUS_SET_BITRATE(opus_codec_settings.maxaveragebitrate));
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opus encoder set bitrate based on maxaveragebitrate found in SDP [%dbps]\n", opus_codec_settings.maxaveragebitrate);
|
||||
} else {
|
||||
opus_encoder_ctl(context->encoder_object, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
|
||||
/* Default codec settings used, may have been modified by SDP "samplerate" */
|
||||
opus_encoder_ctl(context->encoder_object, OPUS_SET_BITRATE(bitrate_bps));
|
||||
if (codec->implementation->actual_samples_per_second == 8000) {
|
||||
opus_encoder_ctl(context->encoder_object, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
|
||||
opus_encoder_ctl(context->encoder_object, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
|
||||
} else {
|
||||
opus_encoder_ctl(context->encoder_object, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
|
||||
}
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opus encoder set bitrate to local settings [%dbps]\n", bitrate_bps);
|
||||
}
|
||||
|
||||
|
||||
/* Another setting from "RTP Payload Format for Opus Speech and Audio Codec" */
|
||||
if ( opus_codec_settings.maxplaybackrate ) {
|
||||
if (opus_codec_settings.maxplaybackrate == 8000) { /* Audio Bandwidth: 0-4000Hz Sampling Rate: 8000Hz */
|
||||
opus_encoder_ctl(context->encoder_object, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
|
||||
} else if (opus_codec_settings.maxplaybackrate == 12000) { /* Audio Bandwidth: 0-6000Hz Sampling Rate: 12000Hz */
|
||||
opus_encoder_ctl(context->encoder_object, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_MEDIUMBAND));
|
||||
} else if (opus_codec_settings.maxplaybackrate == 16000) { /* Audio Bandwidth: 0-8000Hz Sampling Rate: 16000Hz */
|
||||
opus_encoder_ctl(context->encoder_object, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
|
||||
} else if (opus_codec_settings.maxplaybackrate == 24000) { /* Audio Bandwidth: 0-12000Hz Sampling Rate: 24000Hz */
|
||||
opus_encoder_ctl(context->encoder_object, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
|
||||
} else if (opus_codec_settings.maxplaybackrate == 48000) { /* Audio Bandwidth: 0-20000Hz Sampling Rate: 48000Hz */
|
||||
opus_encoder_ctl(context->encoder_object, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
|
||||
}
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opus encoder set bandwidth based on maxplaybackrate found in SDP [%dHz]\n", opus_codec_settings.maxplaybackrate);
|
||||
}
|
||||
|
||||
if (use_vbr) {
|
||||
opus_encoder_ctl(context->encoder_object, OPUS_SET_VBR(use_vbr));
|
||||
}
|
||||
|
@ -428,6 +439,17 @@ static switch_status_t opus_load_config(switch_bool_t reload)
|
|||
opus_prefs.use_vbr = atoi(val);
|
||||
} else if (!strcasecmp(key, "complexity")) {
|
||||
opus_prefs.complexity = atoi(val);
|
||||
} else if (!strcasecmp(key, "maxaveragebitrate")) {
|
||||
opus_prefs.maxaveragebitrate = atoi(val);
|
||||
if ( opus_prefs.maxaveragebitrate < 6000 || opus_prefs.maxaveragebitrate > 510000 ) {
|
||||
opus_prefs.maxaveragebitrate = 0; /* values outside the range between 6000 and 510000 SHOULD be ignored */
|
||||
}
|
||||
} else if (!strcasecmp(key, "maxplaybackrate")) {
|
||||
opus_prefs.maxplaybackrate = atoi(val);
|
||||
if ( opus_prefs.maxplaybackrate != 8000 && opus_prefs.maxplaybackrate != 12000 && opus_prefs.maxplaybackrate != 16000
|
||||
&& opus_prefs.maxplaybackrate != 24000 && opus_prefs.maxplaybackrate != 48000) {
|
||||
opus_prefs.maxplaybackrate = 0; /* value not supported */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,10 +148,15 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *
|
|||
req_nest = switch_true(req_nesta);
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
if ( switch_core_test_flag(SCF_DIALPLAN_TIMESTAMPS) ) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: Processing recursive conditions level:%d [%s] require-nested=%s\n", space,
|
||||
recur, exten_name, req_nest ? "TRUE" : "FALSE");
|
||||
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: Processing recursive conditions level:%d [%s] require-nested=%s\n", space,
|
||||
recur, exten_name, req_nest ? "TRUE" : "FALSE");
|
||||
}
|
||||
} else {
|
||||
if ((tmp = switch_xml_attr(xexten, "name"))) {
|
||||
exten_name = tmp;
|
||||
|
@ -204,15 +209,27 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *
|
|||
}
|
||||
|
||||
if (time_match == 1) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
if ( switch_core_test_flag(SCF_DIALPLAN_TIMESTAMPS) ) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Date/Time Match (PASS) [%s] break=%s\n", space,
|
||||
switch_channel_get_name(channel), exten_name, do_break_a ? do_break_a : "on-false");
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Date/Time Match (PASS) [%s] break=%s\n", space,
|
||||
switch_channel_get_name(channel), exten_name, do_break_a ? do_break_a : "on-false");
|
||||
}
|
||||
anti_action = SWITCH_FALSE;
|
||||
proceed = 1;
|
||||
} else if (time_match == 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
if ( switch_core_test_flag(SCF_DIALPLAN_TIMESTAMPS) ) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Date/TimeMatch (FAIL) [%s] break=%s\n", space,
|
||||
switch_channel_get_name(channel), exten_name, do_break_a ? do_break_a : "on-false");
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Date/TimeMatch (FAIL) [%s] break=%s\n", space,
|
||||
switch_channel_get_name(channel), exten_name, do_break_a ? do_break_a : "on-false");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -230,14 +247,26 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *
|
|||
time_match = switch_xml_std_datetime_check(xregex, tzoff ? &offset : NULL, tzname_);
|
||||
|
||||
if (time_match == 1) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
if ( switch_core_test_flag(SCF_DIALPLAN_TIMESTAMPS) ) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Date/Time Match (PASS) [%s]\n", space,
|
||||
switch_channel_get_name(channel), exten_name);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Date/Time Match (PASS) [%s]\n", space,
|
||||
switch_channel_get_name(channel), exten_name);
|
||||
}
|
||||
anti_action = SWITCH_FALSE;
|
||||
} else if (time_match == 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
if ( switch_core_test_flag(SCF_DIALPLAN_TIMESTAMPS) ) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Date/TimeMatch (FAIL) [%s]\n", space,
|
||||
switch_channel_get_name(channel), exten_name);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Date/TimeMatch (FAIL) [%s]\n", space,
|
||||
switch_channel_get_name(channel), exten_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -273,22 +302,40 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *
|
|||
}
|
||||
|
||||
if ((proceed = switch_regex_perform(field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
if ( switch_core_test_flag(SCF_DIALPLAN_TIMESTAMPS) ) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ match=%s\n", space,
|
||||
switch_channel_get_name(channel), exten_name, field, field_data, expression, all ? "all" : "any");
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ match=%s\n", space,
|
||||
switch_channel_get_name(channel), exten_name, field, field_data, expression, all ? "all" : "any");
|
||||
}
|
||||
pass++;
|
||||
if (!all && !xor) break;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
if ( switch_core_test_flag(SCF_DIALPLAN_TIMESTAMPS) ) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ match=%s\n", space,
|
||||
switch_channel_get_name(channel), exten_name, field, field_data, expression, all ? "all" : "any");
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ match=%s\n", space,
|
||||
switch_channel_get_name(channel), exten_name, field, field_data, expression, all ? "all" : "any");
|
||||
}
|
||||
fail++;
|
||||
if (all && !xor) break;
|
||||
}
|
||||
} else if (time_match == -1) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
if ( switch_core_test_flag(SCF_DIALPLAN_TIMESTAMPS) ) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Absolute Condition [%s] match=%s\n", space,
|
||||
switch_channel_get_name(channel), exten_name, all ? "all" : "any");
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Absolute Condition [%s] match=%s\n", space,
|
||||
switch_channel_get_name(channel), exten_name, all ? "all" : "any");
|
||||
}
|
||||
pass++;
|
||||
proceed = 1;
|
||||
if (!all && !xor) break;
|
||||
|
@ -367,19 +414,37 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *
|
|||
}
|
||||
|
||||
if ((proceed = switch_regex_perform(field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
if ( switch_core_test_flag(SCF_DIALPLAN_TIMESTAMPS) ) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ break=%s\n", space,
|
||||
switch_channel_get_name(channel), exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false");
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ break=%s\n", space,
|
||||
switch_channel_get_name(channel), exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false");
|
||||
}
|
||||
anti_action = SWITCH_FALSE;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
if ( switch_core_test_flag(SCF_DIALPLAN_TIMESTAMPS) ) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ break=%s\n", space,
|
||||
switch_channel_get_name(channel), exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false");
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ break=%s\n", space,
|
||||
switch_channel_get_name(channel), exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false");
|
||||
}
|
||||
}
|
||||
} else if (time_match == -1) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
if ( switch_core_test_flag(SCF_DIALPLAN_TIMESTAMPS) ) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Absolute Condition [%s]\n", space,
|
||||
switch_channel_get_name(channel), exten_name);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Absolute Condition [%s]\n", space,
|
||||
switch_channel_get_name(channel), exten_name);
|
||||
}
|
||||
anti_action = SWITCH_FALSE;
|
||||
proceed = 1;
|
||||
}
|
||||
|
@ -427,9 +492,15 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *
|
|||
}
|
||||
|
||||
for (;loop_count > 0; loop_count--) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
if ( switch_core_test_flag(SCF_DIALPLAN_TIMESTAMPS) ) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s ANTI-Action %s(%s) %s\n", space,
|
||||
switch_channel_get_name(channel), application, data, xinline ? "INLINE" : "");
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s ANTI-Action %s(%s) %s\n", space,
|
||||
switch_channel_get_name(channel), application, data, xinline ? "INLINE" : "");
|
||||
}
|
||||
|
||||
if (xinline) {
|
||||
exec_app(session, application, data);
|
||||
|
@ -488,9 +559,15 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *
|
|||
loop_count = atoi(loop);
|
||||
}
|
||||
for (;loop_count > 0; loop_count--) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
if ( switch_core_test_flag(SCF_DIALPLAN_TIMESTAMPS) ) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Action %s(%s) %s\n", space,
|
||||
switch_channel_get_name(channel), application, app_data, xinline ? "INLINE" : "");
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
"%sDialplan: %s Action %s(%s) %s\n", space,
|
||||
switch_channel_get_name(channel), application, app_data, xinline ? "INLINE" : "");
|
||||
}
|
||||
|
||||
if (xinline) {
|
||||
exec_app(session, application, app_data);
|
||||
|
@ -607,9 +684,15 @@ SWITCH_STANDARD_DIALPLAN(dialplan_hunt)
|
|||
exten_name = "UNKNOWN";
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
if ( switch_core_test_flag(SCF_DIALPLAN_TIMESTAMPS) ) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"Dialplan: %s parsing [%s->%s] continue=%s\n",
|
||||
switch_channel_get_name(channel), caller_profile->context, exten_name, cont ? cont : "false");
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
"Dialplan: %s parsing [%s->%s] continue=%s\n",
|
||||
switch_channel_get_name(channel), caller_profile->context, exten_name, cont ? cont : "false");
|
||||
}
|
||||
|
||||
proceed = parse_exten(session, caller_profile, xexten, &extension, exten_name, 0);
|
||||
|
||||
|
|
|
@ -954,27 +954,29 @@ int channel_on_hangup_callback(void *pArg, int argc, char **argv, char **columnN
|
|||
send_clear_prompt_status(listener, line_instance, call_id);
|
||||
}
|
||||
send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_OFF);
|
||||
switch (helper->cause) {
|
||||
case SWITCH_CAUSE_UNALLOCATED_NUMBER:
|
||||
send_start_tone(listener, SKINNY_TONE_REORDER, 0, line_instance, call_id);
|
||||
skinny_session_send_call_info(helper->tech_pvt->session, listener, line_instance);
|
||||
label = skinny_textid2raw(SKINNY_TEXTID_UNKNOWN_NUMBER);
|
||||
send_display_prompt_status(listener, 0, label, line_instance, call_id);
|
||||
switch_safe_free(label);
|
||||
break;
|
||||
case SWITCH_CAUSE_USER_BUSY:
|
||||
send_start_tone(listener, SKINNY_TONE_BUSYTONE, 0, line_instance, call_id);
|
||||
label = skinny_textid2raw(SKINNY_TEXTID_BUSY);
|
||||
send_display_prompt_status(listener, 0, label, line_instance, call_id);
|
||||
switch_safe_free(label);
|
||||
break;
|
||||
case SWITCH_CAUSE_NORMAL_CLEARING:
|
||||
send_clear_prompt_status(listener, line_instance, call_id);
|
||||
break;
|
||||
default:
|
||||
send_display_prompt_status(listener, 0, switch_channel_cause2str(helper->cause), line_instance, call_id);
|
||||
}
|
||||
|
||||
if((call_state == SKINNY_PROCEED) || (call_state == SKINNY_RING_OUT) || (call_state == SKINNY_CONNECTED)) { /* calling parties */
|
||||
switch (helper->cause) {
|
||||
case SWITCH_CAUSE_UNALLOCATED_NUMBER:
|
||||
send_start_tone(listener, SKINNY_TONE_REORDER, 0, line_instance, call_id);
|
||||
skinny_session_send_call_info(helper->tech_pvt->session, listener, line_instance);
|
||||
label = skinny_textid2raw(SKINNY_TEXTID_UNKNOWN_NUMBER);
|
||||
send_display_prompt_status(listener, 0, label, line_instance, call_id);
|
||||
switch_safe_free(label);
|
||||
break;
|
||||
case SWITCH_CAUSE_USER_BUSY:
|
||||
send_start_tone(listener, SKINNY_TONE_BUSYTONE, 0, line_instance, call_id);
|
||||
label = skinny_textid2raw(SKINNY_TEXTID_BUSY);
|
||||
send_display_prompt_status(listener, 0, label, line_instance, call_id);
|
||||
switch_safe_free(label);
|
||||
break;
|
||||
case SWITCH_CAUSE_NORMAL_CLEARING:
|
||||
send_clear_prompt_status(listener, line_instance, call_id);
|
||||
break;
|
||||
default:
|
||||
send_display_prompt_status(listener, 0, switch_channel_cause2str(helper->cause), line_instance, call_id);
|
||||
}
|
||||
|
||||
skinny_session_stop_media(helper->tech_pvt->session, listener, line_instance);
|
||||
}
|
||||
|
||||
|
|
|
@ -506,9 +506,11 @@ switch_status_t perform_send_register_ack(listener_t *listener,
|
|||
message->data.reg_ack.secondary_keep_alive = keep_alive;
|
||||
switch_copy_string(message->data.reg_ack.reserved2, reserved2, 4);
|
||||
|
||||
skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG,
|
||||
"Sending Register Ack with Keep Alive (%d), Date Format (%s), Secondary Keep Alive (%d)\n",
|
||||
keep_alive, date_format, secondary_keep_alive);
|
||||
if ( listener->profile->debug >= 9 ) {
|
||||
skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG,
|
||||
"Sending Register Ack with Keep Alive (%d), Date Format (%s), Secondary Keep Alive (%d)\n",
|
||||
keep_alive, date_format, secondary_keep_alive);
|
||||
}
|
||||
|
||||
return skinny_send_reply_quiet(listener, message, SWITCH_TRUE);
|
||||
}
|
||||
|
@ -527,9 +529,11 @@ switch_status_t perform_send_speed_dial_stat_res(listener_t *listener,
|
|||
switch_copy_string(message->data.speed_dial_res.line, speed_line, 24);
|
||||
switch_copy_string(message->data.speed_dial_res.label, speed_label, 40);
|
||||
|
||||
skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG,
|
||||
"Sending Speed Dial Stat Res with Number (%d), Line (%s), Label (%s)\n",
|
||||
number, speed_line, speed_label);
|
||||
if ( listener->profile->debug >= 9 ) {
|
||||
skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG,
|
||||
"Sending Speed Dial Stat Res with Number (%d), Line (%s), Label (%s)\n",
|
||||
number, speed_line, speed_label);
|
||||
}
|
||||
|
||||
return skinny_send_reply_quiet(listener, message, SWITCH_TRUE);
|
||||
}
|
||||
|
@ -791,8 +795,10 @@ switch_status_t perform_send_call_info(listener_t *listener,
|
|||
message->data.call_info.call_security_status = call_security_status;
|
||||
message->data.call_info.party_pi_restriction_bits = party_pi_restriction_bits;
|
||||
|
||||
skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG,
|
||||
"Send Call Info with Line Instance (%d)...\n", line_instance);
|
||||
if ( listener->profile->debug >= 9 ) {
|
||||
skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG,
|
||||
"Send Call Info with Line Instance (%d)...\n", line_instance);
|
||||
}
|
||||
|
||||
return skinny_send_reply_quiet(listener, message, SWITCH_TRUE);
|
||||
}
|
||||
|
@ -823,9 +829,11 @@ switch_status_t perform_send_define_time_date(listener_t *listener,
|
|||
message->data.define_time_date.milliseconds = milliseconds;
|
||||
message->data.define_time_date.timestamp = timestamp;
|
||||
|
||||
skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG,
|
||||
"Send Define Time Date with %.4d-%.2d-%.2d %.2d:%.2d:%.2d.%d, Timestamp (%d), DOW (%d)\n",
|
||||
year, month, day, hour, minute, seconds, milliseconds, timestamp, day_of_week);
|
||||
if ( listener->profile->debug >= 9 ) {
|
||||
skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG,
|
||||
"Send Define Time Date with %.4d-%.2d-%.2d %.2d:%.2d:%.2d.%d, Timestamp (%d), DOW (%d)\n",
|
||||
year, month, day, hour, minute, seconds, milliseconds, timestamp, day_of_week);
|
||||
}
|
||||
|
||||
return skinny_send_reply_quiet(listener, message, SWITCH_TRUE);
|
||||
}
|
||||
|
@ -857,8 +865,10 @@ switch_status_t perform_send_capabilities_req(listener_t *listener,
|
|||
|
||||
skinny_create_empty_message(message, CAPABILITIES_REQ_MESSAGE);
|
||||
|
||||
skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG,
|
||||
"Send Capabilities Req%s\n", "");
|
||||
if ( listener->profile->debug >= 9 ) {
|
||||
skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG,
|
||||
"Send Capabilities Req%s\n", "");
|
||||
}
|
||||
|
||||
return skinny_send_reply_quiet(listener, message, SWITCH_TRUE);
|
||||
}
|
||||
|
@ -873,8 +883,10 @@ switch_status_t perform_send_version(listener_t *listener,
|
|||
|
||||
memcpy(message->data.version.version, version, 16);
|
||||
|
||||
skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG,
|
||||
"Send Version with Version(%s)\n", version);
|
||||
if ( listener->profile->debug >= 9 ) {
|
||||
skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG,
|
||||
"Send Version with Version(%s)\n", version);
|
||||
}
|
||||
|
||||
return skinny_send_reply_quiet(listener, message, SWITCH_TRUE);
|
||||
}
|
||||
|
@ -973,9 +985,11 @@ switch_status_t perform_send_select_soft_keys(listener_t *listener,
|
|||
message->data.select_soft_keys.soft_key_set = soft_key_set;
|
||||
message->data.select_soft_keys.valid_key_mask = valid_key_mask;
|
||||
|
||||
skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG,
|
||||
"Send Select Soft Keys with Line Instance (%d), Call ID (%d), Soft Key Set (%d), Valid Key Mask (%x)\n",
|
||||
if ( listener->profile->debug >= 9 ) {
|
||||
skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG,
|
||||
"Send Select Soft Keys with Line Instance (%d), Call ID (%d), Soft Key Set (%d), Valid Key Mask (%x)\n",
|
||||
line_instance, call_id, soft_key_set, valid_key_mask);
|
||||
}
|
||||
|
||||
return skinny_send_reply_quiet(listener, message, SWITCH_TRUE);
|
||||
}
|
||||
|
@ -1299,7 +1313,8 @@ switch_status_t skinny_perform_send_reply(listener_t *listener, const char *file
|
|||
ptr = (char *) reply;
|
||||
|
||||
if (listener_is_ready(listener)) {
|
||||
if (listener->profile->debug >= 10 || reply->type != KEEP_ALIVE_ACK_MESSAGE) {
|
||||
if (listener->profile->debug >= 10 ||
|
||||
(listener->profile->debug >= 9 && reply->type != KEEP_ALIVE_ACK_MESSAGE)) {
|
||||
skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG,
|
||||
"Sending %s (type=%x,length=%d).\n",
|
||||
skinny_message_type2str(reply->type), reply->type, reply->length);
|
||||
|
|
|
@ -1621,8 +1621,10 @@ switch_status_t skinny_handle_forward_stat_req_message(listener_t *listener, ski
|
|||
|
||||
message->data.forward_stat.line_instance = request->data.forward_stat_req.line_instance;
|
||||
|
||||
skinny_log_l(listener, SWITCH_LOG_DEBUG, "Handle Forward Stat Req Message with Line Instance (%d)\n",
|
||||
request->data.forward_stat_req.line_instance);
|
||||
if ( listener->profile->debug >= 9 ) {
|
||||
skinny_log_l(listener, SWITCH_LOG_DEBUG, "Handle Forward Stat Req Message with Line Instance (%d)\n",
|
||||
request->data.forward_stat_req.line_instance);
|
||||
}
|
||||
skinny_send_reply_quiet(listener, message, SWITCH_TRUE);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
@ -1634,7 +1636,9 @@ switch_status_t skinny_handle_speed_dial_stat_request(listener_t *listener, skin
|
|||
|
||||
skinny_check_data_length(request, sizeof(request->data.speed_dial_req));
|
||||
|
||||
skinny_log_l(listener, SWITCH_LOG_DEBUG, "Handle Speed Dial Stat Request for Number (%d)\n", request->data.speed_dial_req.number);
|
||||
if ( listener->profile->debug >= 9 ) {
|
||||
skinny_log_l(listener, SWITCH_LOG_DEBUG, "Handle Speed Dial Stat Request for Number (%d)\n", request->data.speed_dial_req.number);
|
||||
}
|
||||
|
||||
skinny_speed_dial_get(listener, request->data.speed_dial_req.number, &button);
|
||||
|
||||
|
@ -1906,7 +1910,9 @@ switch_status_t skinny_handle_capabilities_response(listener_t *listener, skinny
|
|||
skinny_execute_sql(profile, sql, profile->sql_mutex);
|
||||
switch_safe_free(sql);
|
||||
}
|
||||
skinny_log_l(listener, SWITCH_LOG_DEBUG, "Codecs %s supported.\n", codec_string);
|
||||
if ( listener->profile->debug >= 9 ) {
|
||||
skinny_log_l(listener, SWITCH_LOG_DEBUG, "Codecs %s supported.\n", codec_string);
|
||||
}
|
||||
switch_safe_free(codec_string);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -2036,11 +2042,15 @@ switch_status_t skinny_handle_soft_key_set_request(listener_t *listener, skinny_
|
|||
|
||||
if (listener->soft_key_set_set) {
|
||||
message = switch_core_hash_find(listener->profile->soft_key_set_sets_hash, listener->soft_key_set_set);
|
||||
skinny_log_l(listener, SWITCH_LOG_DEBUG, "Handle Soft Key Set Request with Set (%s)\n", listener->soft_key_set_set);
|
||||
if ( listener->profile->debug >= 9 ) {
|
||||
skinny_log_l(listener, SWITCH_LOG_DEBUG, "Handle Soft Key Set Request with Set (%s)\n", listener->soft_key_set_set);
|
||||
}
|
||||
}
|
||||
if (!message) {
|
||||
message = switch_core_hash_find(listener->profile->soft_key_set_sets_hash, "default");
|
||||
skinny_log_l(listener, SWITCH_LOG_DEBUG, "Handle Soft Key Set Request with Set (%s)\n", "default");
|
||||
if ( listener->profile->debug >= 9 ) {
|
||||
skinny_log_l(listener, SWITCH_LOG_DEBUG, "Handle Soft Key Set Request with Set (%s)\n", "default");
|
||||
}
|
||||
}
|
||||
if (message) {
|
||||
skinny_send_reply_quiet(listener, message, SWITCH_FALSE);
|
||||
|
@ -2231,7 +2241,9 @@ switch_status_t skinny_handle_soft_key_template_request(listener_t *listener, sk
|
|||
message->data.soft_key_template.soft_key[i].soft_key_event = soft_key_template_default_events[i];
|
||||
}
|
||||
|
||||
skinny_log_l_msg(listener, SWITCH_LOG_DEBUG, "Handle Soft Key Template Request with Default Template\n");
|
||||
if ( listener->profile->debug >= 9 ) {
|
||||
skinny_log_l_msg(listener, SWITCH_LOG_DEBUG, "Handle Soft Key Template Request with Default Template\n");
|
||||
}
|
||||
|
||||
skinny_send_reply_quiet(listener, message, SWITCH_TRUE);
|
||||
|
||||
|
@ -2254,8 +2266,10 @@ switch_status_t skinny_headset_status_message(listener_t *listener, skinny_messa
|
|||
switch_safe_free(sql);
|
||||
}
|
||||
|
||||
skinny_log_l(listener, SWITCH_LOG_DEBUG, "Update headset accessory status (%s)\n",
|
||||
skinny_accessory_state2str(request->data.headset_status.mode));
|
||||
if ( listener->profile->debug >= 9 ) {
|
||||
skinny_log_l(listener, SWITCH_LOG_DEBUG, "Update headset accessory status (%s)\n",
|
||||
skinny_accessory_state2str(request->data.headset_status.mode));
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -2274,7 +2288,9 @@ switch_status_t skinny_handle_register_available_lines_message(listener_t *liste
|
|||
{
|
||||
skinny_check_data_length(request, sizeof(request->data.reg_lines));
|
||||
|
||||
skinny_log_l_msg(listener, SWITCH_LOG_DEBUG, "Handle Register Available Lines\n");
|
||||
if ( listener->profile->debug >= 9 ) {
|
||||
skinny_log_l_msg(listener, SWITCH_LOG_DEBUG, "Handle Register Available Lines\n");
|
||||
}
|
||||
|
||||
/* Do nothing */
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
@ -2531,7 +2547,7 @@ switch_status_t skinny_handle_xml_alarm(listener_t *listener, skinny_message_t *
|
|||
switch_event_t *event = NULL;
|
||||
char *tmp = NULL;
|
||||
|
||||
skinny_log_l(listener, SWITCH_LOG_INFO, "Received XML alarm (length=%d).\n", request->length);
|
||||
skinny_log_l(listener, SWITCH_LOG_DEBUG, "Received XML alarm (length=%d).\n", request->length);
|
||||
/* skinny::xml_alarm event */
|
||||
skinny_device_event(listener, &event, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_XML_ALARM);
|
||||
/* Ensure that the body is null-terminated */
|
||||
|
@ -2547,7 +2563,8 @@ switch_status_t skinny_handle_xml_alarm(listener_t *listener, skinny_message_t *
|
|||
|
||||
switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *request)
|
||||
{
|
||||
if (listener->profile->debug >= 10 || request->type != KEEP_ALIVE_MESSAGE) {
|
||||
if (listener->profile->debug >= 10 ||
|
||||
(listener->profile->debug >= 9 && request->type != KEEP_ALIVE_MESSAGE)) {
|
||||
skinny_log_l(listener, SWITCH_LOG_DEBUG, "Received %s (type=%x,length=%d).\n",
|
||||
skinny_message_type2str(request->type), request->type, request->length);
|
||||
}
|
||||
|
|
|
@ -1471,6 +1471,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
|
|||
case SWITCH_MESSAGE_INDICATE_PHONE_EVENT:
|
||||
{
|
||||
const char *event = "talk";
|
||||
const char *full_to = NULL;
|
||||
|
||||
if (!zstr(msg->string_arg) && strcasecmp(msg->string_arg, event)) {
|
||||
if (!strcasecmp(msg->string_arg, "hold")) {
|
||||
|
@ -1484,7 +1485,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
|
|||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,
|
||||
"Operation not permitted on an inbound non-answered call leg!\n");
|
||||
} else {
|
||||
nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), NUTAG_SUBSTATE(nua_substate_active), SIPTAG_SUBSCRIPTION_STATE_STR("active"),
|
||||
full_to = switch_str_nil(switch_channel_get_variable(channel, "sip_full_to"));
|
||||
nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), NUTAG_SUBSTATE(nua_substate_active),
|
||||
TAG_IF((full_to), SIPTAG_TO_STR(full_to)),SIPTAG_SUBSCRIPTION_STATE_STR("active"),
|
||||
SIPTAG_EVENT_STR(event), TAG_END());
|
||||
}
|
||||
|
||||
|
@ -2932,15 +2935,27 @@ static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handl
|
|||
for (x = 0; x < profile->rtpip_index; x++) {
|
||||
stream->write_function(stream, " <rtp-ip>%s</rtp-ip>\n", switch_str_nil(profile->rtpip[x]));
|
||||
}
|
||||
stream->write_function(stream, " <ext-rtp-ip>%s</ext-rtp-ip>\n", profile->extrtpip);
|
||||
if (profile->extrtpip) {
|
||||
stream->write_function(stream, " <ext-rtp-ip>%s</ext-rtp-ip>\n", profile->extrtpip);
|
||||
}
|
||||
stream->write_function(stream, " <sip-ip>%s</sip-ip>\n", switch_str_nil(profile->sipip));
|
||||
stream->write_function(stream, " <ext-sip-ip>%s</ext-sip-ip>\n", profile->extsipip);
|
||||
stream->write_function(stream, " <url>%s</url>\n", switch_str_nil(profile->url));
|
||||
stream->write_function(stream, " <bind-url>%s</bind-url>\n", switch_str_nil(profile->bindurl));
|
||||
stream->write_function(stream, " <tls-url>%s</tls-url>\n", switch_str_nil(profile->tls_url));
|
||||
stream->write_function(stream, " <tls-bind-url>%s</tls-bind-url>\n", switch_str_nil(profile->tls_bindurl));
|
||||
stream->write_function(stream, " <ws-bind-url>%s</ws-bind-url>\n", switch_str_nil(profile->ws_bindurl));
|
||||
stream->write_function(stream, " <wss-bind-url>%s</wss-bind-url>\n", switch_str_nil(profile->wss_bindurl));
|
||||
if (profile->extsipip) {
|
||||
stream->write_function(stream, " <ext-sip-ip>%s</ext-sip-ip>\n", profile->extsipip);
|
||||
}
|
||||
if (! sofia_test_pflag(profile, PFLAG_TLS) || ! profile->tls_only) {
|
||||
stream->write_function(stream, " <url>%s</url>\n", switch_str_nil(profile->url));
|
||||
stream->write_function(stream, " <bind-url>%s</bind-url>\n", switch_str_nil(profile->bindurl));
|
||||
}
|
||||
if (sofia_test_pflag(profile, PFLAG_TLS)) {
|
||||
stream->write_function(stream, " <tls-url>%s</tls-url>\n", switch_str_nil(profile->tls_url));
|
||||
stream->write_function(stream, " <tls-bind-url>%s</tls-bind-url>\n", switch_str_nil(profile->tls_bindurl));
|
||||
}
|
||||
if (profile->ws_bindurl) {
|
||||
stream->write_function(stream, " <ws-bind-url>%s</ws-bind-url>\n", switch_str_nil(profile->ws_bindurl));
|
||||
}
|
||||
if (profile->wss_bindurl) {
|
||||
stream->write_function(stream, " <wss-bind-url>%s</wss-bind-url>\n", switch_str_nil(profile->wss_bindurl));
|
||||
}
|
||||
stream->write_function(stream, " <hold-music>%s</hold-music>\n", zstr(profile->hold_music) ? "N/A" : profile->hold_music);
|
||||
stream->write_function(stream, " <outbound-proxy>%s</outbound-proxy>\n",
|
||||
zstr(profile->outbound_proxy) ? "N/A" : profile->outbound_proxy);
|
||||
|
@ -2948,9 +2963,13 @@ static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handl
|
|||
stream->write_function(stream, " <outbound-codecs>%s</outbound-codecs>\n", switch_str_nil(profile->outbound_codec_string));
|
||||
|
||||
stream->write_function(stream, " <tel-event>%d</tel-event>\n", profile->te);
|
||||
stream->write_function(stream, " <dtmf-mode>rfc2833</dtmf-mode>\n");
|
||||
stream->write_function(stream, " <dtmf-mode>info</dtmf-mode>\n");
|
||||
stream->write_function(stream, " <dtmf-mode>none</dtmf-mode>\n");
|
||||
if (profile->dtmf_type == DTMF_2833) {
|
||||
stream->write_function(stream, " <dtmf-mode>rfc2833</dtmf-mode>\n");
|
||||
} else if (profile->dtmf_type == DTMF_INFO) {
|
||||
stream->write_function(stream, " <dtmf-mode>info</dtmf-mode>\n");
|
||||
} else {
|
||||
stream->write_function(stream, " <dtmf-mode>none</dtmf-mode>\n");
|
||||
}
|
||||
stream->write_function(stream, " <cng>%d</cng>\n", profile->cng_pt);
|
||||
stream->write_function(stream, " <session-to>%d</session-to>\n", profile->session_timeout);
|
||||
stream->write_function(stream, " <max-dialog>%d</max-dialog>\n", profile->max_proceeding);
|
||||
|
@ -2960,9 +2979,13 @@ static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handl
|
|||
stream->write_function(stream, " <zrtp-passthru>%s</zrtp-passthru>\n", sofia_test_flag(profile, TFLAG_ZRTP_PASSTHRU) ? "true" : "false");
|
||||
stream->write_function(stream, " <aggressive-nat>%s</aggressive-nat>\n",
|
||||
sofia_test_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION) ? "true" : "false");
|
||||
stream->write_function(stream, " <user-agent-filter>%s</user-agent-filter>\n", switch_str_nil(profile->user_agent_filter));
|
||||
stream->write_function(stream, " <max-registrations-per-extension>%d</max-registrations-per-extension>\n",
|
||||
if (profile->user_agent_filter) {
|
||||
stream->write_function(stream, " <user-agent-filter>%s</user-agent-filter>\n", switch_str_nil(profile->user_agent_filter));
|
||||
}
|
||||
if (profile->max_registrations_perext > 0) {
|
||||
stream->write_function(stream, " <max-registrations-per-extension>%d</max-registrations-per-extension>\n",
|
||||
profile->max_registrations_perext);
|
||||
}
|
||||
stream->write_function(stream, " <calls-in>%u</calls-in>\n", profile->ib_calls);
|
||||
stream->write_function(stream, " <calls-out>%u</calls-out>\n", profile->ob_calls);
|
||||
stream->write_function(stream, " <failed-calls-in>%u</failed-calls-in>\n", profile->ib_failed_calls);
|
||||
|
|
|
@ -810,6 +810,8 @@ struct private_object {
|
|||
time_t last_vid_info;
|
||||
uint32_t keepalive;
|
||||
uint32_t sent_invites;
|
||||
uint32_t recv_invites;
|
||||
uint8_t sent_last_invite;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -6538,9 +6538,17 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
|||
if (!tech_pvt || !tech_pvt->nh) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((status > 100 || switch_channel_test_flag(channel, CF_ANSWERED)) && status < 300 && !r_sdp && tech_pvt->mparams.last_sdp_str) {
|
||||
r_sdp = tech_pvt->mparams.last_sdp_str;
|
||||
|
||||
if (!r_sdp && (status > 100 || switch_channel_test_flag(channel, CF_ANSWERED)) && status < 300) {
|
||||
if (ss_state == nua_callstate_ready) {
|
||||
if (tech_pvt->mparams.last_sdp_response) {
|
||||
r_sdp = tech_pvt->mparams.last_sdp_response;
|
||||
}
|
||||
} else {
|
||||
if (tech_pvt->mparams.last_sdp_str) {
|
||||
r_sdp = tech_pvt->mparams.last_sdp_str;
|
||||
}
|
||||
}
|
||||
}
|
||||
tech_pvt->mparams.last_sdp_str = NULL;
|
||||
|
||||
|
@ -6657,10 +6665,19 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
|||
}
|
||||
|
||||
if (channel && (status == 180 || status == 183) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
const char *full_to = NULL;
|
||||
const char *val;
|
||||
if ((val = switch_channel_get_variable(channel, "sip_auto_answer")) && switch_true(val)) {
|
||||
nua_notify(nh, NUTAG_NEWSUB(1), NUTAG_WITH_THIS_MSG(de->data->e_msg),
|
||||
NUTAG_SUBSTATE(nua_substate_terminated),SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"), SIPTAG_EVENT_STR("talk"), TAG_END());
|
||||
full_to = switch_str_nil(switch_channel_get_variable(channel, "sip_full_to"));
|
||||
|
||||
nua_notify(nh,
|
||||
NUTAG_NEWSUB(1),
|
||||
NUTAG_WITH_THIS_MSG(de->data->e_msg),
|
||||
NUTAG_SUBSTATE(nua_substate_terminated),
|
||||
TAG_IF((full_to), SIPTAG_TO_STR(full_to)),
|
||||
SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"),
|
||||
SIPTAG_EVENT_STR("talk"),
|
||||
TAG_END());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6688,6 +6705,8 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
|||
case nua_callstate_authenticating:
|
||||
break;
|
||||
case nua_callstate_calling:
|
||||
tech_pvt->sent_last_invite = 1;
|
||||
tech_pvt->sent_invites++;
|
||||
break;
|
||||
case nua_callstate_proceeding:
|
||||
|
||||
|
@ -6826,6 +6845,8 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
|||
}
|
||||
goto done;
|
||||
case nua_callstate_received:
|
||||
tech_pvt->recv_invites++;
|
||||
tech_pvt->sent_last_invite = 0;
|
||||
if (!sofia_test_flag(tech_pvt, TFLAG_SDP)) {
|
||||
if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
|
||||
private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
|
||||
|
@ -9913,7 +9934,15 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia
|
|||
|
||||
/* Loop thru unknown Headers Here so we can do something with them */
|
||||
for (un = sip->sip_unknown; un; un = un->un_next) {
|
||||
if (!strncasecmp(un->un_name, "Diversion", 9)) {
|
||||
if (!strncasecmp(un->un_name, "Accept-Language", 15)) {
|
||||
if (!zstr(un->un_value)) {
|
||||
char *tmp_name;
|
||||
if ((tmp_name = switch_mprintf("%s%s", SOFIA_SIP_HEADER_PREFIX, un->un_name))) {
|
||||
switch_channel_set_variable(channel, tmp_name, un->un_value);
|
||||
free(tmp_name);
|
||||
}
|
||||
}
|
||||
} else if (!strncasecmp(un->un_name, "Diversion", 9)) {
|
||||
/* Basic Diversion Support for Diversion Indication in SIP */
|
||||
/* draft-levy-sip-diversion-08 */
|
||||
if (!zstr(un->un_value)) {
|
||||
|
|
|
@ -1233,7 +1233,11 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
|
|||
switch_channel_get_name(tech_pvt->channel), switch_version_full_human(),
|
||||
tech_pvt->mparams.local_sdp_str ? tech_pvt->mparams.local_sdp_str : "NO SDP PRESENT\n");
|
||||
|
||||
tech_pvt->sent_invites++;
|
||||
|
||||
|
||||
if (switch_channel_get_private(tech_pvt->channel, "t38_options")) {
|
||||
sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA);
|
||||
}
|
||||
|
||||
if (sofia_use_soa(tech_pvt)) {
|
||||
nua_invite(tech_pvt->nh,
|
||||
|
@ -1268,6 +1272,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
|
|||
TAG_IF(!zstr(tech_pvt->mparams.local_sdp_str), SOATAG_ADDRESS(tech_pvt->mparams.adv_sdp_audio_ip)),
|
||||
TAG_IF(!zstr(tech_pvt->mparams.local_sdp_str), SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str)),
|
||||
TAG_IF(!zstr(tech_pvt->mparams.local_sdp_str), SOATAG_REUSE_REJECTED(1)),
|
||||
TAG_IF(switch_channel_get_private(tech_pvt->channel, "t38_options"), SOATAG_ORDERED_USER(1)),
|
||||
TAG_IF(!zstr(tech_pvt->mparams.local_sdp_str), SOATAG_RTP_SORT(SOA_RTP_SORT_REMOTE)),
|
||||
TAG_IF(!zstr(tech_pvt->mparams.local_sdp_str), SOATAG_RTP_SELECT(SOA_RTP_SELECT_ALL)),
|
||||
TAG_IF(rep, SIPTAG_REPLACES_STR(rep)),
|
||||
|
|
|
@ -1572,7 +1572,9 @@ uint8_t sofia_reg_handle_register_token(nua_t *nua, sofia_profile_t *profile, nu
|
|||
if (!is_tcp && !is_tls && (zstr(network_ip) || !switch_check_network_list_ip(network_ip, profile->local_network)) &&
|
||||
profile->server_rport_level >= 2 && sip->sip_user_agent &&
|
||||
sip->sip_user_agent->g_string &&
|
||||
( !strncasecmp(sip->sip_user_agent->g_string, "Polycom", 7) || !strncasecmp(sip->sip_user_agent->g_string, "KIRK Wireless Server", 20) )) {
|
||||
( !strncasecmp(sip->sip_user_agent->g_string, "Polycom", 7) ||
|
||||
!strncasecmp(sip->sip_user_agent->g_string, "KIRK Wireless Server", 20) ||
|
||||
!strncasecmp(sip->sip_user_agent->g_string, "ADTRAN_Total_Access", 19) )) {
|
||||
if (sip && sip->sip_via) {
|
||||
const char *host = sip->sip_via->v_host;
|
||||
const char *c_port = sip->sip_via->v_port;
|
||||
|
|
|
@ -4286,7 +4286,7 @@ static switch_status_t parse_config(const char *cf)
|
|||
}
|
||||
|
||||
if (zstr(vhost->script_root)) {
|
||||
vhost->root = SWITCH_GLOBAL_dirs.script_dir;
|
||||
vhost->script_root = SWITCH_GLOBAL_dirs.script_dir;
|
||||
}
|
||||
|
||||
if (zstr(vhost->index)) {
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
include $(top_srcdir)/build/modmake.rulesam
|
||||
MODNAME=mod_odbc_cdr
|
||||
|
||||
mod_LTLIBRARIES = mod_odbc_cdr.la
|
||||
mod_odbc_cdr_la_SOURCES = mod_odbc_cdr.c
|
||||
mod_odbc_cdr_la_CFLAGS = $(AM_CFLAGS)
|
||||
mod_odbc_cdr_la_LIBADD = $(switch_builddir)/libfreeswitch.la
|
||||
mod_odbc_cdr_la_LDFLAGS = -avoid-version -module -no-undefined -shared
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
<configuration name="odbc_cdr.conf" description="ODBC CDR Configuration">
|
||||
<settings>
|
||||
<!-- <param name="odbc-dsn" value="database:username:password"/> -->
|
||||
<param name="odbc-dsn" value="pgsql://hostaddr=192.168.0.100 dbname=freeswitch user=freeswitch password='freeswitch' options='-c client_min_messages=NOTICE'"/>
|
||||
<!-- global value can be "a-leg", "b-leg", "both" (default is "both") -->
|
||||
<param name="log-leg" value="both"/>
|
||||
<!-- value can be "always", "never", "on-db-fail" -->
|
||||
<param name="write-csv" value="on-db-fail"/>
|
||||
<!-- location to store csv copy of CDR -->
|
||||
<param name="csv-path" value="/usr/local/freeswitch/log/odbc_cdr"/>
|
||||
<!-- if "csv-path-on-fail" is set, failed INSERTs will be placed here as CSV files otherwise they will be placed in "csv-path" -->
|
||||
<param name="csv-path-on-fail" value="/usr/local/freeswitch/log/odbc_cdr/failed"/>
|
||||
<!-- dump SQL statement after leg ends -->
|
||||
<param name="debug-sql" value="true"/>
|
||||
</settings>
|
||||
<tables>
|
||||
<!-- only a-legs will be inserted into this table -->
|
||||
<table name="cdr_table_a_leg" log-leg="a-leg">
|
||||
<field name="CallId" chan-var-name="call_uuid"/>
|
||||
<field name="orig_id" chan-var-name="uuid"/>
|
||||
<field name="term_id" chan-var-name="sip_call_id"/>
|
||||
<field name="ClientId" chan-var-name="uuid"/>
|
||||
<field name="IP" chan-var-name="sip_network_ip"/>
|
||||
<field name="IPInternal" chan-var-name="sip_via_host"/>
|
||||
<field name="CODEC" chan-var-name="read_codec"/>
|
||||
<field name="directGateway" chan-var-name="sip_req_host"/>
|
||||
<field name="redirectGateway" chan-var-name="sip_redirect_contact_host_0"/>
|
||||
<field name="CallerID" chan-var-name="sip_from_user"/>
|
||||
<field name="TelNumber" chan-var-name="sip_req_user"/>
|
||||
<field name="TelNumberFull" chan-var-name="sip_to_user"/>
|
||||
<field name="sip_endpoint_disposition" chan-var-name="endpoint_disposition"/>
|
||||
<field name="sip_current_application" chan-var-name="current_application"/>
|
||||
</table>
|
||||
<!-- only b-legs will be inserted into this table -->
|
||||
<table name="cdr_table_b_leg" log-leg="b-leg">
|
||||
<field name="CallId" chan-var-name="call_uuid"/>
|
||||
<field name="orig_id" chan-var-name="uuid"/>
|
||||
<field name="term_id" chan-var-name="sip_call_id"/>
|
||||
<field name="ClientId" chan-var-name="uuid"/>
|
||||
<field name="IP" chan-var-name="sip_network_ip"/>
|
||||
<field name="IPInternal" chan-var-name="sip_via_host"/>
|
||||
<field name="CODEC" chan-var-name="read_codec"/>
|
||||
<field name="directGateway" chan-var-name="sip_req_host"/>
|
||||
<field name="redirectGateway" chan-var-name="sip_redirect_contact_host_0"/>
|
||||
<field name="CallerID" chan-var-name="sip_from_user"/>
|
||||
<field name="TelNumber" chan-var-name="sip_req_user"/>
|
||||
<field name="TelNumberFull" chan-var-name="sip_to_user"/>
|
||||
<field name="sip_endpoint_disposition" chan-var-name="endpoint_disposition"/>
|
||||
<field name="sip_current_application" chan-var-name="current_application"/>
|
||||
</table>
|
||||
<!-- both legs will be inserted into this table -->
|
||||
<table name="cdr_table_both">
|
||||
<field name="CallId" chan-var-name="uuid"/>
|
||||
<field name="orig_id" chan-var-name="Caller-Unique-ID"/>
|
||||
<field name="TEST_id" chan-var-name="sip_from_uri"/>
|
||||
</table>
|
||||
</tables>
|
||||
</configuration>
|
|
@ -0,0 +1,565 @@
|
|||
/*
|
||||
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2005-2012, 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):
|
||||
*
|
||||
* Emmanuel Schmidbauer <e.schmidbauer@gmail.com>
|
||||
*
|
||||
* mod_odbc_cdr.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include "switch.h"
|
||||
|
||||
#define ODBC_CDR_SQLITE_DB_NAME "odbc_cdr"
|
||||
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_odbc_cdr_shutdown);
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_odbc_cdr_load);
|
||||
SWITCH_MODULE_DEFINITION(mod_odbc_cdr, mod_odbc_cdr_load, mod_odbc_cdr_shutdown, NULL);
|
||||
|
||||
static const char *global_cf = "odbc_cdr.conf";
|
||||
|
||||
typedef enum {
|
||||
ODBC_CDR_LOG_A,
|
||||
ODBC_CDR_LOG_B,
|
||||
ODBC_CDR_LOG_BOTH
|
||||
} odbc_cdr_log_leg_t;
|
||||
|
||||
typedef enum {
|
||||
ODBC_CDR_CSV_ALWAYS,
|
||||
ODBC_CDR_CSV_NEVER,
|
||||
ODBC_CDR_CSV_ON_FAIL
|
||||
} odbc_cdr_write_csv_t;
|
||||
|
||||
static struct {
|
||||
char *odbc_dsn;
|
||||
char *dbname;
|
||||
char *csv_path;
|
||||
char *csv_fail_path;
|
||||
odbc_cdr_log_leg_t log_leg;
|
||||
odbc_cdr_write_csv_t write_csv;
|
||||
switch_bool_t debug_sql;
|
||||
switch_hash_t *table_hash;
|
||||
uint32_t running;
|
||||
switch_mutex_t *mutex;
|
||||
switch_memory_pool_t *pool;
|
||||
} globals;
|
||||
|
||||
struct table_profile {
|
||||
char *name;
|
||||
odbc_cdr_log_leg_t log_leg;
|
||||
switch_hash_t *field_hash;
|
||||
uint32_t flags;
|
||||
switch_mutex_t *mutex;
|
||||
switch_memory_pool_t *pool;
|
||||
};
|
||||
typedef struct table_profile table_profile_t;
|
||||
|
||||
static table_profile_t *load_table(const char *table_name)
|
||||
{
|
||||
table_profile_t *table = NULL;
|
||||
switch_xml_t x_tables, cfg, xml, x_table, x_field;
|
||||
|
||||
if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf);
|
||||
return table;
|
||||
}
|
||||
|
||||
if (!(x_tables = switch_xml_child(cfg, "tables"))) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((x_table = switch_xml_find_child(x_tables, "table", "name", table_name))) {
|
||||
switch_memory_pool_t *pool;
|
||||
char *table_log_leg = (char *) switch_xml_attr_soft(x_table, "log-leg");
|
||||
|
||||
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Pool Failure\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!(table = switch_core_alloc(pool, sizeof(table_profile_t)))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Alloc Failure\n");
|
||||
switch_core_destroy_memory_pool(&pool);
|
||||
goto end;
|
||||
}
|
||||
|
||||
table->pool = pool;
|
||||
|
||||
switch_mutex_init(&table->mutex, SWITCH_MUTEX_NESTED, table->pool);
|
||||
|
||||
table->name = switch_core_strdup(pool, table_name);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Found table [%s]\n", table->name);
|
||||
|
||||
if (!strcasecmp(table_log_leg, "a-leg")) {
|
||||
table->log_leg = ODBC_CDR_LOG_A;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set table [%s] to log A-legs only\n", table->name);
|
||||
} else if (!strcasecmp(table_log_leg, "b-leg")) {
|
||||
table->log_leg = ODBC_CDR_LOG_B;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set table [%s] to log B-legs only\n", table->name);
|
||||
} else {
|
||||
table->log_leg = ODBC_CDR_LOG_BOTH;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set table [%s] to log both legs\n", table->name);
|
||||
}
|
||||
|
||||
switch_core_hash_init(&table->field_hash);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Adding fields to table [%s]\n", table->name);
|
||||
|
||||
for (x_field = switch_xml_child(x_table, "field"); x_field; x_field = x_field->next) {
|
||||
char *var = (char *) switch_xml_attr_soft(x_field, "name");
|
||||
char *val = (char *) switch_xml_attr_soft(x_field, "chan-var-name");
|
||||
char *value = NULL;
|
||||
if (zstr(var) || zstr(val)) {
|
||||
continue; // Ignore empty entries
|
||||
}
|
||||
value = switch_core_strdup(pool, val);
|
||||
switch_core_hash_insert_locked(table->field_hash, var, value, table->mutex);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Field [%s] (%s) added to [%s]\n", var, val, table->name);
|
||||
}
|
||||
|
||||
switch_core_hash_insert(globals.table_hash, table->name, table);
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
if (xml) {
|
||||
switch_xml_free(xml);
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
switch_cache_db_handle_t *get_db_handle(void)
|
||||
{
|
||||
switch_cache_db_handle_t *dbh = NULL;
|
||||
char *dsn;
|
||||
if (!zstr(globals.odbc_dsn)) {
|
||||
dsn = globals.odbc_dsn;
|
||||
} else {
|
||||
dsn = globals.dbname;
|
||||
}
|
||||
if (switch_cache_db_get_db_handle_dsn(&dbh, dsn) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB\n");
|
||||
dbh = NULL;
|
||||
}
|
||||
return dbh;
|
||||
}
|
||||
|
||||
static switch_status_t odbc_cdr_execute_sql_no_callback(char *sql)
|
||||
{
|
||||
switch_cache_db_handle_t *dbh = NULL;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
||||
if (!(dbh = get_db_handle())) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
status = switch_cache_db_execute_sql(dbh, sql, NULL);
|
||||
|
||||
end:
|
||||
|
||||
switch_cache_db_release_db_handle(&dbh);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void write_cdr(const char *path, const char *log_line)
|
||||
{
|
||||
int fd = -1;
|
||||
#ifdef _MSC_VER
|
||||
if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) > -1) {
|
||||
#else
|
||||
if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) > -1) {
|
||||
#endif
|
||||
int wrote;
|
||||
wrote = write(fd, log_line, (unsigned) strlen(log_line));
|
||||
wrote += write(fd, "\n", 1);
|
||||
wrote++;
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static switch_status_t odbc_cdr_reporting(switch_core_session_t *session)
|
||||
{
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
switch_memory_pool_t *pool = switch_core_session_get_pool(session);
|
||||
switch_caller_profile_t *caller_profile = switch_channel_get_caller_profile(channel);
|
||||
switch_hash_index_t *hi;
|
||||
const void *var;
|
||||
void *val;
|
||||
switch_console_callback_match_t *matches = NULL;
|
||||
switch_console_callback_match_node_t *m;
|
||||
const char *uuid = NULL;
|
||||
|
||||
if (globals.log_leg == ODBC_CDR_LOG_A && caller_profile->direction == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Only logging A-Leg, ignoring B-leg\n");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
} else if (globals.log_leg == ODBC_CDR_LOG_B && caller_profile->direction == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Only logging B-Leg, ignoring A-leg\n");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!(uuid = switch_channel_get_variable(channel, "uuid"))) {
|
||||
uuid = switch_core_strdup(pool, caller_profile->uuid);
|
||||
}
|
||||
|
||||
// copy all table names from global hash
|
||||
switch_mutex_lock(globals.mutex);
|
||||
for (hi = switch_core_hash_first(globals.table_hash); hi; hi = switch_core_hash_next(&hi)) {
|
||||
switch_core_hash_this(hi, &var, NULL, &val);
|
||||
switch_console_push_match(&matches, (const char *) var);
|
||||
}
|
||||
switch_mutex_unlock(globals.mutex);
|
||||
|
||||
if (matches) {
|
||||
table_profile_t *table = NULL;
|
||||
|
||||
// loop through table names
|
||||
for (m = matches->head; m; m = m->next) {
|
||||
char *table_name = m->val;
|
||||
switch_bool_t started = SWITCH_FALSE;
|
||||
switch_bool_t skip_leg = SWITCH_FALSE;
|
||||
|
||||
switch_mutex_lock(globals.mutex);
|
||||
table = switch_core_hash_find(globals.table_hash, table_name);
|
||||
switch_mutex_unlock(globals.mutex);
|
||||
|
||||
if (!table) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Table [%s] not found, ignoring leg\n", table_name);
|
||||
skip_leg = SWITCH_TRUE;
|
||||
}
|
||||
|
||||
if (table->log_leg == ODBC_CDR_LOG_A && caller_profile->direction == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
skip_leg = SWITCH_TRUE;
|
||||
}
|
||||
|
||||
if (table->log_leg == ODBC_CDR_LOG_B && caller_profile->direction == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
skip_leg = SWITCH_TRUE;
|
||||
}
|
||||
|
||||
if (skip_leg == SWITCH_FALSE) {
|
||||
switch_hash_index_t *i_hi = NULL;
|
||||
const void *i_var;
|
||||
void *i_val;
|
||||
char *field_hash_key;
|
||||
char *field_hash_val;
|
||||
char *sql = NULL;
|
||||
char *full_path = NULL;
|
||||
switch_stream_handle_t stream_field = { 0 };
|
||||
switch_stream_handle_t stream_value = { 0 };
|
||||
switch_bool_t insert_fail = SWITCH_FALSE;
|
||||
|
||||
SWITCH_STANDARD_STREAM(stream_field);
|
||||
SWITCH_STANDARD_STREAM(stream_value);
|
||||
|
||||
for (i_hi = switch_core_hash_first_iter( table->field_hash, i_hi); i_hi; i_hi = switch_core_hash_next(&i_hi)) {
|
||||
const char *tmp;
|
||||
switch_core_hash_this(i_hi, &i_var, NULL, &i_val);
|
||||
field_hash_key = (char *) i_var;
|
||||
field_hash_val = (char *) i_val;
|
||||
|
||||
if ((tmp = switch_channel_get_variable(channel, field_hash_val))) {
|
||||
if (started == SWITCH_FALSE) {
|
||||
stream_field.write_function(&stream_field, "%s", field_hash_key);
|
||||
stream_value.write_function(&stream_value, "'%s'", tmp);
|
||||
} else {
|
||||
stream_field.write_function(&stream_field, ", %s", field_hash_key);
|
||||
stream_value.write_function(&stream_value, ", '%s'", tmp);
|
||||
}
|
||||
started = SWITCH_TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
switch_safe_free(i_hi);
|
||||
|
||||
sql = switch_mprintf("INSERT INTO %s (%s) VALUES (%s)", table_name, stream_field.data, stream_value.data);
|
||||
if (globals.debug_sql == SWITCH_TRUE) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sql %s\n", sql);
|
||||
}
|
||||
if (odbc_cdr_execute_sql_no_callback(sql) == SWITCH_STATUS_FALSE) {
|
||||
insert_fail = SWITCH_TRUE;
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error executing query %s\n", sql);
|
||||
}
|
||||
|
||||
if (globals.write_csv == ODBC_CDR_CSV_ALWAYS) {
|
||||
if (insert_fail == SWITCH_TRUE) {
|
||||
full_path = switch_mprintf("%s%s%s.csv", globals.csv_fail_path, SWITCH_PATH_SEPARATOR, uuid);
|
||||
} else {
|
||||
full_path = switch_mprintf("%s%s%s.csv", globals.csv_path, SWITCH_PATH_SEPARATOR, uuid);
|
||||
}
|
||||
assert(full_path);
|
||||
write_cdr(full_path, stream_value.data);
|
||||
switch_safe_free(full_path);
|
||||
} else if (globals.write_csv == ODBC_CDR_CSV_ON_FAIL && insert_fail == SWITCH_TRUE) {
|
||||
full_path = switch_mprintf("%s%s%s.csv", globals.csv_fail_path, SWITCH_PATH_SEPARATOR, uuid);
|
||||
assert(full_path);
|
||||
write_cdr(full_path, stream_value.data);
|
||||
switch_safe_free(full_path);
|
||||
}
|
||||
|
||||
switch_safe_free(sql);
|
||||
|
||||
switch_safe_free(stream_field.data);
|
||||
switch_safe_free(stream_value.data);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
switch_console_free_matches(&matches);
|
||||
}
|
||||
|
||||
switch_safe_free(hi);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
switch_state_handler_table_t odbc_cdr_state_handlers = {
|
||||
/*.on_init */ NULL,
|
||||
/*.on_routing */ NULL,
|
||||
/*.on_execute */ NULL,
|
||||
/*.on_hangup */ NULL,
|
||||
/*.on_exchange_media */ NULL,
|
||||
/*.on_soft_execute */ NULL,
|
||||
/*.on_consume_media */ NULL,
|
||||
/*.on_hibernate */ NULL,
|
||||
/*.on_reset */ NULL,
|
||||
/*.on_park */ NULL,
|
||||
/*.on_reporting */ odbc_cdr_reporting,
|
||||
/*.on_destroy */ NULL
|
||||
};
|
||||
|
||||
static switch_status_t odbc_cdr_load_config(void)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
switch_xml_t cfg, xml, settings, param, tables, table;
|
||||
switch_cache_db_handle_t *dbh = NULL;
|
||||
|
||||
switch_mutex_lock(globals.mutex);
|
||||
|
||||
if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf);
|
||||
status = SWITCH_STATUS_TERM;
|
||||
goto end;
|
||||
}
|
||||
|
||||
globals.debug_sql = SWITCH_FALSE;
|
||||
globals.log_leg = ODBC_CDR_LOG_BOTH;
|
||||
globals.write_csv = ODBC_CDR_CSV_NEVER;
|
||||
|
||||
if ((settings = switch_xml_child(cfg, "settings")) != NULL) {
|
||||
for (param = switch_xml_child(settings, "param"); param; param = param->next) {
|
||||
char *var = (char *) switch_xml_attr_soft(param, "name");
|
||||
char *val = (char *) switch_xml_attr_soft(param, "value");
|
||||
|
||||
if (zstr(var) || zstr(val)) {
|
||||
continue; // Ignore empty entries
|
||||
}
|
||||
if (!strcasecmp(var, "dbname")) {
|
||||
globals.dbname = strdup(val);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set dbname [%s]\n", globals.dbname);
|
||||
} else if (!strcasecmp(var, "odbc-dsn")) {
|
||||
globals.odbc_dsn = strdup(val);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set odbc-dsn [%s]\n", globals.odbc_dsn);
|
||||
} else if (!strcasecmp(var, "log-leg")) {
|
||||
if (!strcasecmp(val, "a-leg")) {
|
||||
globals.log_leg = ODBC_CDR_LOG_A;
|
||||
} else if (!strcasecmp(val, "b-leg")) {
|
||||
globals.log_leg = ODBC_CDR_LOG_B;
|
||||
}
|
||||
} else if (!strcasecmp(var, "debug-sql") && switch_true(val)) {
|
||||
globals.debug_sql = SWITCH_TRUE;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set debug-sql [true]\n");
|
||||
} else if (!strcasecmp(var, "write-csv") && !zstr(val)) {
|
||||
if (!strcasecmp(val, "always")) {
|
||||
globals.write_csv = ODBC_CDR_CSV_ALWAYS;
|
||||
} else if (!strcasecmp(val, "on-db-fail")) {
|
||||
globals.write_csv = ODBC_CDR_CSV_ON_FAIL;
|
||||
}
|
||||
} else if (!strcasecmp(var, "csv-path") && !zstr(val)) {
|
||||
globals.csv_path = switch_mprintf("%s%s", val, SWITCH_PATH_SEPARATOR);
|
||||
} else if (!strcasecmp(var, "csv-path-on-fail") && !zstr(val)) {
|
||||
globals.csv_fail_path = switch_mprintf("%s%s", val, SWITCH_PATH_SEPARATOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (globals.log_leg == ODBC_CDR_LOG_A) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set log-leg [a-leg]\n");
|
||||
} else if (globals.log_leg == ODBC_CDR_LOG_B) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set log-leg [b-leg]\n");
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set log-leg [both]\n");
|
||||
}
|
||||
|
||||
if (!globals.csv_path) {
|
||||
globals.csv_path = switch_mprintf("%s%sodbc-cdr", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR);
|
||||
}
|
||||
|
||||
if (!globals.csv_fail_path) {
|
||||
globals.csv_fail_path = switch_mprintf("%s%sodbc-cdr-failed", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR);
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set csv-path [%s]\n", globals.csv_path);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set csv-path-on-fail [%s]\n", globals.csv_fail_path);
|
||||
|
||||
if ((tables = switch_xml_child(cfg, "tables"))) {
|
||||
for (table = switch_xml_child(tables, "table"); table; table = table->next) {
|
||||
load_table(switch_xml_attr_soft(table, "name"));
|
||||
}
|
||||
}
|
||||
|
||||
if (!globals.dbname) {
|
||||
globals.dbname = strdup(ODBC_CDR_SQLITE_DB_NAME);
|
||||
}
|
||||
|
||||
// Initialize database
|
||||
if (!(dbh = get_db_handle())) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot open DB!\n");
|
||||
status = SWITCH_STATUS_TERM;
|
||||
goto end;
|
||||
}
|
||||
|
||||
switch_cache_db_release_db_handle(&dbh);
|
||||
|
||||
end:
|
||||
switch_mutex_unlock(globals.mutex);
|
||||
|
||||
if (xml) {
|
||||
switch_xml_free(xml);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_odbc_cdr_load)
|
||||
{
|
||||
switch_status_t status;
|
||||
|
||||
memset(&globals, 0, sizeof(globals));
|
||||
switch_core_hash_init(&globals.table_hash);
|
||||
if (switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, pool) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to initialize mutex\n");
|
||||
}
|
||||
globals.pool = pool;
|
||||
|
||||
if ((status = odbc_cdr_load_config()) != SWITCH_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (globals.write_csv != ODBC_CDR_CSV_NEVER) {
|
||||
if ((status = switch_dir_make_recursive(globals.csv_path, SWITCH_DEFAULT_DIR_PERMS, pool)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", globals.csv_path);
|
||||
return status;
|
||||
}
|
||||
if (strcasecmp(globals.csv_path, globals.csv_fail_path)) {
|
||||
if ((status = switch_dir_make_recursive(globals.csv_fail_path, SWITCH_DEFAULT_DIR_PERMS, pool)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", globals.csv_path);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch_mutex_lock(globals.mutex);
|
||||
globals.running = 1;
|
||||
switch_mutex_unlock(globals.mutex);
|
||||
|
||||
switch_core_add_state_handler(&odbc_cdr_state_handlers);
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
|
||||
/* 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_odbc_cdr_shutdown() */
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_odbc_cdr_shutdown)
|
||||
{
|
||||
switch_hash_index_t *hi = NULL;
|
||||
table_profile_t *table;
|
||||
void *val = NULL;
|
||||
const void *key;
|
||||
switch_ssize_t keylen;
|
||||
|
||||
switch_mutex_lock(globals.mutex);
|
||||
if (globals.running == 1) {
|
||||
globals.running = 0;
|
||||
}
|
||||
|
||||
while ((hi = switch_core_hash_first_iter(globals.table_hash, hi))) {
|
||||
switch_hash_index_t *field_hi = NULL;
|
||||
void *field_val = NULL;
|
||||
const void *field_key;
|
||||
switch_ssize_t field_keylen;
|
||||
|
||||
switch_core_hash_this(hi, &key, &keylen, &val);
|
||||
table = (table_profile_t *) val;
|
||||
|
||||
while ((field_hi = switch_core_hash_first_iter(table->field_hash, field_hi))) {
|
||||
switch_core_hash_this(field_hi, &field_key, &field_keylen, &field_val);
|
||||
switch_core_hash_delete_locked(table->field_hash, field_key, table->mutex);
|
||||
}
|
||||
switch_core_hash_destroy(&table->field_hash);
|
||||
switch_safe_free(field_hi);
|
||||
|
||||
switch_core_hash_delete(globals.table_hash, table->name);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Destroying table %s\n", table->name);
|
||||
|
||||
switch_core_destroy_memory_pool(&table->pool);
|
||||
table = NULL;
|
||||
}
|
||||
switch_core_hash_destroy(&globals.table_hash);
|
||||
switch_safe_free(hi);
|
||||
|
||||
switch_safe_free(globals.csv_path)
|
||||
switch_safe_free(globals.csv_fail_path)
|
||||
switch_safe_free(globals.odbc_dsn);
|
||||
switch_safe_free(globals.dbname);
|
||||
|
||||
switch_mutex_unlock(globals.mutex);
|
||||
switch_mutex_destroy(globals.mutex);
|
||||
|
||||
switch_core_remove_state_handler(&odbc_cdr_state_handlers);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4
|
||||
*/
|
|
@ -2,8 +2,14 @@
|
|||
|
||||
<!-- rayo params -->
|
||||
<settings>
|
||||
<!-- ends idle calls : unbridged calls that have not been controlled by client in some time -->
|
||||
<param name="max-idle-sec" value="300"/>
|
||||
<!-- conference profile to use for mixers- sla = shared line appearance / conference /w no audio -->
|
||||
<param name="mixer-conf-profile" value="sla"/>
|
||||
<!-- if true, to attribute in offer uses URI instead of name/number -->
|
||||
<param name="offer-uri" value="true"/>
|
||||
<!-- if true, channel variables are added to rayo client offer -->
|
||||
<param name="add-variables-to-offer" value="false"/>
|
||||
</settings>
|
||||
|
||||
<!-- record component params -->
|
||||
|
@ -52,8 +58,8 @@
|
|||
|
||||
<!-- map mod_spandsp call progress tone detector to Rayo CPA signal events. Fires DETECTED_TONE events until stopped. -->
|
||||
<detector name="mod_spandsp_tone">
|
||||
<start application="start_tone_detect" data="1"/>
|
||||
<stop application="stop_tone_detect" data=""/>
|
||||
<start application="spandsp_start_tone_detect" data="1"/>
|
||||
<stop application="spandsp_stop_tone_detect" data=""/>
|
||||
<!-- map tone events to Rayo CPA signal type -->
|
||||
<event class="CUSTOM" subclass="DETECTED_TONE" type-header="Detected-Tone">
|
||||
<signal-type header-value="SIT" value="sit"/>
|
||||
|
|
|
@ -229,6 +229,8 @@ static struct {
|
|||
int pause_when_offline;
|
||||
/** flag to reduce log noise */
|
||||
int offline_logged;
|
||||
/** if true, channel variables are added to offer */
|
||||
int add_variables_to_offer;
|
||||
} globals;
|
||||
|
||||
/**
|
||||
|
@ -3682,18 +3684,23 @@ static iks *rayo_create_offer(struct rayo_call *call, switch_core_session_t *ses
|
|||
iks_insert_attrib(offer, "to", profile->destination_number);
|
||||
}
|
||||
|
||||
/* add signaling headers */
|
||||
/* add headers to offer */
|
||||
{
|
||||
switch_event_header_t *var;
|
||||
add_header(offer, "from", switch_channel_get_variable(channel, "sip_full_from"));
|
||||
add_header(offer, "to", switch_channel_get_variable(channel, "sip_full_to"));
|
||||
add_header(offer, "via", switch_channel_get_variable(channel, "sip_full_via"));
|
||||
|
||||
/* get all variables prefixed with sip_h_ */
|
||||
/* add all SIP header variables and (if configured) all other variables */
|
||||
for (var = switch_channel_variable_first(channel); var; var = var->next) {
|
||||
if (!strncmp("sip_h_", var->name, 6)) {
|
||||
add_header(offer, var->name + 6, var->value);
|
||||
}
|
||||
if (globals.add_variables_to_offer) {
|
||||
char var_name[1024];
|
||||
snprintf(var_name, 1024, "variable-%s", var->name);
|
||||
add_header(offer, var_name, var->value);
|
||||
}
|
||||
}
|
||||
switch_channel_variable_last(channel);
|
||||
}
|
||||
|
@ -4066,6 +4073,7 @@ static switch_status_t do_config(switch_memory_pool_t *pool, const char *config_
|
|||
globals.num_message_threads = 8;
|
||||
globals.offer_uri = 1;
|
||||
globals.pause_when_offline = 0;
|
||||
globals.add_variables_to_offer = 0;
|
||||
|
||||
/* get params */
|
||||
{
|
||||
|
@ -4102,6 +4110,10 @@ static switch_status_t do_config(switch_memory_pool_t *pool, const char *config_
|
|||
if (switch_true(val)) {
|
||||
globals.pause_when_offline = 1;
|
||||
}
|
||||
} else if (!strcasecmp(var, "add-variables-to-offer")) {
|
||||
if (switch_true(val)) {
|
||||
globals.add_variables_to_offer = 1;
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unsupported param: %s\n", var);
|
||||
}
|
||||
|
|
|
@ -368,6 +368,8 @@ struct rayo_file_context {
|
|||
struct rayo_component *component;
|
||||
/** number of times played */
|
||||
int play_count;
|
||||
/** have any files successfully opened? */
|
||||
int could_open;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -376,6 +378,7 @@ struct rayo_file_context {
|
|||
*/
|
||||
static switch_status_t next_file(switch_file_handle_t *handle)
|
||||
{
|
||||
int loops = 0;
|
||||
struct rayo_file_context *context = handle->private_info;
|
||||
struct output_component *output = context->component ? OUTPUT_COMPONENT(context->component) : NULL;
|
||||
|
||||
|
@ -404,7 +407,7 @@ static switch_status_t next_file(switch_file_handle_t *handle)
|
|||
|
||||
/* done? */
|
||||
if (!context->cur_doc) {
|
||||
if (output->repeat_times == 0 || ++context->play_count < output->repeat_times) {
|
||||
if (context->could_open && ++loops < 2 && (output->repeat_times == 0 || ++context->play_count < output->repeat_times)) {
|
||||
/* repeat all document(s) */
|
||||
if (!output->repeat_interval_ms) {
|
||||
goto top;
|
||||
|
@ -464,6 +467,8 @@ static switch_status_t next_file(switch_file_handle_t *handle)
|
|||
if (switch_core_file_open(&context->fh, context->ssml, handle->channels, handle->samplerate, handle->flags, NULL) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Failed to open %s\n", context->ssml);
|
||||
goto top;
|
||||
} else {
|
||||
context->could_open = 1;
|
||||
}
|
||||
|
||||
handle->samples = context->fh.samples;
|
||||
|
@ -503,6 +508,7 @@ static switch_status_t rayo_file_open(switch_file_handle_t *handle, const char *
|
|||
handle->private_info = context;
|
||||
context->cur_doc = NULL;
|
||||
context->play_count = 0;
|
||||
context->could_open = 0;
|
||||
status = next_file(handle);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "File error! %s\n", path);
|
||||
|
|
|
@ -450,7 +450,7 @@ static void xmpp_send_outbound_server_header(struct xmpp_stream *stream)
|
|||
static void on_stream_starttls(struct xmpp_stream *stream, iks *node)
|
||||
{
|
||||
/* wait for handshake to start */
|
||||
if (iks_proceed_tls(stream->parser, stream->context->cert_pem_file, stream->context->key_pem_file, 1) == IKS_OK) {
|
||||
if (iks_proceed_tls(stream->parser, stream->context->cert_pem_file, stream->context->key_pem_file) == IKS_OK) {
|
||||
stream->state = XSS_SECURE;
|
||||
} else {
|
||||
stream->state = XSS_ERROR;
|
||||
|
|
|
@ -123,6 +123,7 @@ struct shout_context {
|
|||
int lame_ready;
|
||||
int eof;
|
||||
int channels;
|
||||
int stream_channels;
|
||||
int16_t *l;
|
||||
switch_size_t llen;
|
||||
int16_t *r;
|
||||
|
@ -371,14 +372,25 @@ static size_t stream_callback(void *ptr, size_t size, size_t nmemb, void *data)
|
|||
shout_context_t *context = data;
|
||||
int decode_status = 0;
|
||||
size_t usedlen;
|
||||
uint32_t buf_size = 1024 * 128; /* do not make this 64 or less, stutter will ensue after
|
||||
first 64k buffer is dry */
|
||||
uint32_t buf_size = 1024 * 128; /* do not make this 64 or less, stutter will ensue after first 64k buffer is dry */
|
||||
switch_size_t used;
|
||||
|
||||
if (!context->stream_channels) {
|
||||
long rate = 0;
|
||||
int channels = 0;
|
||||
int encoding = 0;
|
||||
mpg123_getformat(context->mh, &rate, &channels, &encoding);
|
||||
context->stream_channels = channels;
|
||||
}
|
||||
|
||||
if (context->prebuf) {
|
||||
buf_size = context->prebuf;
|
||||
}
|
||||
|
||||
if (context->stream_channels) {
|
||||
buf_size = buf_size * context->stream_channels;
|
||||
}
|
||||
|
||||
/* make sure we aren't over zealous by slowing down the stream when the buffer is too full */
|
||||
while (!context->err) {
|
||||
switch_mutex_lock(context->audio_mutex);
|
||||
|
|
|
@ -54,10 +54,13 @@ struct sndfile_context {
|
|||
|
||||
typedef struct sndfile_context sndfile_context;
|
||||
|
||||
static switch_status_t sndfile_perform_open(sndfile_context *context, const char *path, const char *mask, int mode);
|
||||
|
||||
static switch_status_t sndfile_file_open(switch_file_handle_t *handle, const char *path)
|
||||
{
|
||||
sndfile_context *context;
|
||||
int mode = 0;
|
||||
const char *mask = "rb";
|
||||
char *ext;
|
||||
struct format_map *map = NULL;
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
|
@ -84,8 +87,10 @@ static switch_status_t sndfile_file_open(switch_file_handle_t *handle, const cha
|
|||
|
||||
if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
|
||||
if (switch_test_flag(handle, SWITCH_FILE_WRITE_APPEND) || switch_test_flag(handle, SWITCH_FILE_WRITE_OVER) || handle->offset_pos) {
|
||||
mask = "ab+";
|
||||
mode += SFM_RDWR;
|
||||
} else {
|
||||
mask = "wb+";
|
||||
mode += SFM_WRITE;
|
||||
}
|
||||
}
|
||||
|
@ -181,7 +186,7 @@ static switch_status_t sndfile_file_open(switch_file_handle_t *handle, const cha
|
|||
ldup = strdup(last);
|
||||
switch_assert(ldup);
|
||||
switch_snprintf(last, alt_len - (last - alt_path), "%d%s%s", handle->samplerate, SWITCH_PATH_SEPARATOR, ldup);
|
||||
if ((context->handle = sf_open(alt_path, mode, &context->sfinfo))) {
|
||||
if (sndfile_perform_open(context, alt_path, mask, mode) == SWITCH_STATUS_SUCCESS) {
|
||||
path = alt_path;
|
||||
} else {
|
||||
/* Try to find the file at the highest rate possible if we can't find one that matches the exact rate.
|
||||
|
@ -189,7 +194,7 @@ static switch_status_t sndfile_file_open(switch_file_handle_t *handle, const cha
|
|||
*/
|
||||
for (i = 3; i >= 0; i--) {
|
||||
switch_snprintf(last, alt_len - (last - alt_path), "%d%s%s", rates[i], SWITCH_PATH_SEPARATOR, ldup);
|
||||
if ((context->handle = sf_open(alt_path, mode, &context->sfinfo))) {
|
||||
if (sndfile_perform_open(context, alt_path, mask, mode) == SWITCH_STATUS_SUCCESS) {
|
||||
path = alt_path;
|
||||
break;
|
||||
}
|
||||
|
@ -198,7 +203,7 @@ static switch_status_t sndfile_file_open(switch_file_handle_t *handle, const cha
|
|||
}
|
||||
|
||||
if (!context->handle) {
|
||||
if ((context->handle = sf_open(path, mode, &context->sfinfo)) == 0) {
|
||||
if (sndfile_perform_open(context, path, mask, mode) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening File [%s] [%s]\n", path, sf_strerror(context->handle));
|
||||
status = SWITCH_STATUS_GENERR;
|
||||
goto end;
|
||||
|
@ -236,6 +241,20 @@ static switch_status_t sndfile_file_open(switch_file_handle_t *handle, const cha
|
|||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t sndfile_perform_open(sndfile_context *context, const char *path, const char *mask, int mode)
|
||||
{
|
||||
FILE *fd = NULL;
|
||||
fd = fopen(path, mask);
|
||||
if (!fd) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
if ((context->handle = sf_open_fd(fileno(fd), mode, &context->sfinfo, SWITCH_TRUE)) == 0) {
|
||||
fclose(fd);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t sndfile_file_truncate(switch_file_handle_t *handle, int64_t offset)
|
||||
{
|
||||
sndfile_context *context = handle->private_info;
|
||||
|
|
|
@ -394,9 +394,9 @@ bool Dbh::test_reactive(char *test_sql, char *drop_sql, char *reactive_sql)
|
|||
if (switch_cache_db_test_reactive(dbh, test_sql, drop_sql, reactive_sql) == SWITCH_TRUE) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DBH NOT Connected.\n");
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DBH NOT Connected.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
* Michael Giagnocavo <mgg@giagnocavo.net>
|
||||
* David Brazier <David.Brazier@360crm.co.uk>
|
||||
* Jeff Lenk <jeff@jefflenk.com>
|
||||
* Artur Kraev <ravenox@gmail.com>
|
||||
*
|
||||
* Loader.cs -- mod_managed loader
|
||||
*
|
||||
|
@ -33,7 +34,6 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
@ -47,7 +47,7 @@ namespace FreeSWITCH {
|
|||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate bool ExecuteBackgroundDelegate(string cmd);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate bool RunDelegate(string cmd, IntPtr session);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate bool ReloadDelegate(string cmd);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate bool ListDelegate(string cmd);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate bool ListDelegate(string cmd, IntPtr streamH, IntPtr eventH);
|
||||
static readonly ExecuteDelegate _execute = Execute;
|
||||
static readonly ExecuteBackgroundDelegate _executeBackground = ExecuteBackground;
|
||||
static readonly RunDelegate _run = Run;
|
||||
|
@ -66,7 +66,12 @@ namespace FreeSWITCH {
|
|||
managedDir = Path.Combine(Native.freeswitch.SWITCH_GLOBAL_dirs.mod_dir, "managed");
|
||||
shadowDir = Path.Combine(managedDir, "shadow");
|
||||
if (Directory.Exists(shadowDir)) {
|
||||
Directory.Delete(shadowDir, true);
|
||||
try {
|
||||
Directory.Delete(shadowDir, true);
|
||||
} catch (Exception ex) {
|
||||
Log.WriteLine(LogLevel.Warning, "Cannot delete shadow directory: {0}", ex);
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(shadowDir);
|
||||
}
|
||||
|
||||
|
@ -220,11 +225,35 @@ namespace FreeSWITCH {
|
|||
setup.ConfigurationFile = fileName + ".config";
|
||||
}
|
||||
setup.ApplicationBase = Native.freeswitch.SWITCH_GLOBAL_dirs.mod_dir;
|
||||
setup.ShadowCopyDirectories = managedDir + ";";
|
||||
setup.LoaderOptimization = LoaderOptimization.MultiDomainHost; // TODO: would MultiDomain work better since FreeSWITCH.Managed isn't gac'd?
|
||||
setup.CachePath = shadowDir;
|
||||
setup.ShadowCopyFiles = "true";
|
||||
setup.PrivateBinPath = "managed";
|
||||
|
||||
// computing private bin path
|
||||
var binPath = setup.PrivateBinPath ?? string.Empty;
|
||||
|
||||
var binPaths = binPath.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(x => x.Trim())
|
||||
.ToList();
|
||||
|
||||
// adding "managed" (modules) directory
|
||||
if (!binPaths.Contains("managed")) {
|
||||
binPaths.Add("managed");
|
||||
}
|
||||
|
||||
// adding "managed/<modulename>" directory for per-module references support
|
||||
var moduleRefsDir = Path.GetFileName(fileName);
|
||||
moduleRefsDir = Path.GetFileNameWithoutExtension(moduleRefsDir);
|
||||
|
||||
if (moduleRefsDir != null && moduleRefsDir.Trim() != "") {
|
||||
moduleRefsDir = Path.Combine("managed", moduleRefsDir);
|
||||
if (!binPaths.Contains(moduleRefsDir, StringComparer.OrdinalIgnoreCase)) {
|
||||
binPaths.Add(moduleRefsDir);
|
||||
}
|
||||
}
|
||||
|
||||
// bringing all together
|
||||
setup.PrivateBinPath = string.Join(";", binPaths);
|
||||
|
||||
// Create domain and load PM inside
|
||||
System.Threading.Interlocked.Increment(ref appDomainCount);
|
||||
|
@ -408,16 +437,24 @@ namespace FreeSWITCH {
|
|||
}
|
||||
}
|
||||
|
||||
public static bool List(string command) {
|
||||
public static bool List(string command, IntPtr streamHandle, IntPtr eventHandle)
|
||||
{
|
||||
try {
|
||||
Log.WriteLine(LogLevel.Info, "Available APIs:");
|
||||
getApiExecs().Values.ForEach(x => {
|
||||
Log.WriteLine(LogLevel.Info, "{0}: {1}", x.Name, String.Join(",", x.Aliases.ToArray()));
|
||||
});
|
||||
Log.WriteLine(LogLevel.Info, "Available Apps:");
|
||||
getAppExecs().Values.ForEach(x => {
|
||||
Log.WriteLine(LogLevel.Info, "{0}: {1}", x.Name, String.Join(",", x.Aliases.ToArray()));
|
||||
});
|
||||
if (streamHandle != IntPtr.Zero) {
|
||||
using (var stream = new Native.Stream(new Native.switch_stream_handle(streamHandle, false))) {
|
||||
stream.Write("Available APIs:\n");
|
||||
|
||||
getApiExecs().Values.ForEach(x => stream.Write(string.Format("{0}: {1}\n", x.Name, String.Join(",", x.Aliases.ToArray()))));
|
||||
|
||||
stream.Write("Available Apps:\n");
|
||||
getAppExecs().Values.ForEach(x => stream.Write(string.Format("{0}: {1}\n", x.Name, String.Join(",", x.Aliases.ToArray()))));
|
||||
}
|
||||
} else {
|
||||
Log.WriteLine(LogLevel.Info, "Available APIs:");
|
||||
getApiExecs().Values.ForEach(x => Log.WriteLine(LogLevel.Info, "{0}: {1}", x.Name, String.Join(",", x.Aliases.ToArray())));
|
||||
Log.WriteLine(LogLevel.Info, "Available Apps:");
|
||||
getAppExecs().Values.ForEach(x => Log.WriteLine(LogLevel.Info, "{0}: {1}", x.Name, String.Join(",", x.Aliases.ToArray())));
|
||||
}
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
Log.WriteLine(LogLevel.Error, "Exception listing managed modules: {0}", ex.ToString());
|
||||
|
|
|
@ -57,6 +57,7 @@ namespace FreeSWITCH
|
|||
static string ToLogString(this LogLevel level)
|
||||
{
|
||||
switch (level) {
|
||||
case LogLevel.Console: return "CONSOLE";
|
||||
case LogLevel.Alert: return "ALERT";
|
||||
case LogLevel.Critical: return "CRIT";
|
||||
case LogLevel.Debug: return "DEBUG";
|
||||
|
@ -85,6 +86,7 @@ namespace FreeSWITCH
|
|||
};*/
|
||||
public enum LogLevel
|
||||
{
|
||||
Console,
|
||||
Debug,
|
||||
Info,
|
||||
Error,
|
||||
|
|
|
@ -149,6 +149,23 @@ namespace FreeSWITCH.Native
|
|||
};
|
||||
return del;
|
||||
}
|
||||
|
||||
/// <summary>Wraps a nice handler into a delegate suitable for reverse P/Invoke. For native api using</summary>
|
||||
public static switch_state_handler_t_delegate CreateStateHandlerDelegate(Action<ManagedSession> handler)
|
||||
{
|
||||
// We create a ManagedSession on top of the session so callbacks can use it "nicely"
|
||||
// Then we sort of dispose it.
|
||||
switch_state_handler_t_delegate del = ptr =>
|
||||
{
|
||||
using (var sess = new ManagedSession(new SWIGTYPE_p_switch_core_session(ptr, false)))
|
||||
{
|
||||
handler(sess);
|
||||
return switch_status_t.SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
};
|
||||
return del;
|
||||
}
|
||||
|
||||
public static SWIGTYPE_p_f_p_switch_core_session__switch_status_t WrapStateHandlerDelegate(switch_state_handler_t_delegate del) {
|
||||
return new SWIGTYPE_p_f_p_switch_core_session__switch_status_t(Marshal.GetFunctionPointerForDelegate(del), false);
|
||||
}
|
||||
|
|
|
@ -46,5 +46,31 @@ namespace FreeSWITCH {
|
|||
if (cons == null) throw new ArgumentException(ty.Name + " constructor not found.");
|
||||
return (T)cons.Invoke(new object[] { cPtr, false });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Getting IntPtr from wrapper
|
||||
/// </summary>
|
||||
/// <typeparam name="T">swig generated class</typeparam>
|
||||
/// <param name="obj">instance</param>
|
||||
/// <returns>Original pointer</returns>
|
||||
public static IntPtr GetPtr<T>(T obj)
|
||||
{
|
||||
// internal static HandleRef getCPtr(CoreSession obj)
|
||||
var ty = typeof(T);
|
||||
var bflags = BindingFlags.Static | BindingFlags.NonPublic;
|
||||
var getCPtr = ty.GetMethod("getCPtr", bflags, null, new[] { typeof(T) }, null);
|
||||
|
||||
if (getCPtr != null)
|
||||
{
|
||||
var handleRef = getCPtr.Invoke(null, new object[] { obj });
|
||||
|
||||
if (handleRef is HandleRef)
|
||||
{
|
||||
return ((HandleRef)handleRef).Handle;
|
||||
}
|
||||
}
|
||||
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
* Michael Giagnocavo <mgg@giagnocavo.net>
|
||||
* David Brazier <David.Brazier@360crm.co.uk>
|
||||
* Jeff Lenk <jlenk@frontiernet.net>
|
||||
* Artur Kraev <ravenox@gmail.com>
|
||||
*
|
||||
* mod_mono.cpp -- FreeSWITCH mod_mono main class
|
||||
*
|
||||
|
@ -73,14 +74,14 @@ typedef int (*runFunction)(const char *data, void *sessionPtr);
|
|||
typedef int (*executeFunction)(const char *cmd, void *stream, void *Event);
|
||||
typedef int (*executeBackgroundFunction)(const char* cmd);
|
||||
typedef int (*reloadFunction)(const char* cmd);
|
||||
typedef int (*listFunction)(const char* cmd);
|
||||
typedef int (*listFunction)(const char *cmd, void *stream, void *Event);
|
||||
static runFunction runDelegate;
|
||||
static executeFunction executeDelegate;
|
||||
static executeBackgroundFunction executeBackgroundDelegate;
|
||||
static reloadFunction reloadDelegate;
|
||||
static listFunction listDelegate;
|
||||
|
||||
SWITCH_MOD_DECLARE_NONSTD(void) InitManagedDelegates(runFunction run, executeFunction execute, executeBackgroundFunction executeBackground, reloadFunction reload, listFunction list)
|
||||
SWITCH_MOD_DECLARE_NONSTD(void) InitManagedDelegates(runFunction run, executeFunction execute, executeBackgroundFunction executeBackground, reloadFunction reload, listFunction list)
|
||||
{
|
||||
runDelegate = run;
|
||||
executeDelegate = execute;
|
||||
|
@ -451,7 +452,7 @@ SWITCH_STANDARD_API(managedlist_api_function)
|
|||
#ifndef _MANAGED
|
||||
mono_thread_attach(globals.domain);
|
||||
#endif
|
||||
listDelegate(cmd);
|
||||
listDelegate(cmd, stream, stream->param_event);
|
||||
#ifndef _MANAGED
|
||||
mono_thread_detach(mono_thread_current());
|
||||
#endif
|
||||
|
|
|
@ -394,9 +394,9 @@ bool Dbh::test_reactive(char *test_sql, char *drop_sql, char *reactive_sql)
|
|||
if (switch_cache_db_test_reactive(dbh, test_sql, drop_sql, reactive_sql) == SWITCH_TRUE) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DBH NOT Connected.\n");
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DBH NOT Connected.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
include $(top_srcdir)/build/modmake.rulesam
|
||||
MODNAME=mod_say_es_ar
|
||||
|
||||
mod_LTLIBRARIES = mod_say_es_ar.la
|
||||
mod_say_es_ar_la_SOURCES = mod_say_es_ar.c
|
||||
mod_say_es_ar_la_CFLAGS = $(AM_CFLAGS)
|
||||
mod_say_es_ar_la_LIBADD = $(switch_builddir)/libfreeswitch.la
|
||||
mod_say_es_ar_la_LDFLAGS = -avoid-version -module -no-undefined -shared
|
|
@ -0,0 +1,718 @@
|
|||
/*
|
||||
* Copyright (c) 2007-2014, Anthony Minessale II
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Michael B. Murdock <mike@mmurdock.org>
|
||||
* François Delawarde <fdelawarde@wirelessmundi.com>
|
||||
* Joao Mesquita <jmesquita@freeswitch.org>
|
||||
*
|
||||
* mod_say_es_ar.c -- Say for Spanish (Argentina)
|
||||
*
|
||||
*/
|
||||
|
||||
#include <switch.h>
|
||||
#include <math.h>
|
||||
#include <ctype.h>
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_say_es_ar_load);
|
||||
SWITCH_MODULE_DEFINITION(mod_say_es_ar, mod_say_es_ar_load, NULL, NULL);
|
||||
|
||||
|
||||
#define say_num(_sh, num, meth) { \
|
||||
char tmp[80]; \
|
||||
switch_status_t tstatus; \
|
||||
switch_say_method_t smeth = say_args->method; \
|
||||
switch_say_type_t stype = say_args->type; \
|
||||
say_args->type = SST_ITEMS; say_args->method = meth; \
|
||||
switch_snprintf(tmp, sizeof(tmp), "%u", (unsigned)num); \
|
||||
if ((tstatus = \
|
||||
es_say_general_count(_sh, tmp, say_args)) \
|
||||
!= SWITCH_STATUS_SUCCESS) { \
|
||||
return tstatus; \
|
||||
} \
|
||||
say_args->method = smeth; say_args->type = stype; \
|
||||
} \
|
||||
|
||||
|
||||
|
||||
static switch_status_t play_group(switch_say_method_t method, switch_say_gender_t gender, int a, int b, int c, char *what, switch_say_file_handle_t *sh)
|
||||
{
|
||||
|
||||
if (a) {
|
||||
if (a == 1 && b == 0 && c == 0) {
|
||||
switch_say_file(sh, "digits/hundred");
|
||||
} else {
|
||||
switch_say_file(sh, "digits/%d00", a);
|
||||
}
|
||||
}
|
||||
|
||||
if (b) {
|
||||
if (method == SSM_COUNTED) {
|
||||
/* Numeros no redondos es masculino siempre. */
|
||||
if (gender == SSG_FEMININE && c == 0) {
|
||||
switch_say_file(sh, "digits/h-%d0_a", b);
|
||||
|
||||
} else {
|
||||
switch_say_file(sh, "digits/h-%d0", b);
|
||||
}
|
||||
} else {
|
||||
/* Veinti */
|
||||
if (b == 2) {
|
||||
switch_say_file(sh, "digits/%d0_i", b);
|
||||
} else if(b == 1) {
|
||||
switch_say_file(sh, "digits/%d%d", b, c);
|
||||
} else {
|
||||
switch_say_file(sh, "digits/%d0", b);
|
||||
if (c > 0) {
|
||||
switch_say_file(sh, "digits/y");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (c && b != 1) {
|
||||
if (method == SSM_COUNTED) {
|
||||
if (gender == SSG_FEMININE) {
|
||||
switch_say_file(sh, "digits/h-%d_a", c);
|
||||
} else {
|
||||
switch_say_file(sh, "digits/h-%d", c);
|
||||
}
|
||||
} else {
|
||||
if (c == 1) {
|
||||
if (gender == SSG_NEUTER) {
|
||||
switch_say_file(sh, "digits/%d_n", c);
|
||||
} else if (gender == SSG_FEMININE) {
|
||||
switch_say_file(sh, "digits/%d_a", c);
|
||||
} else {
|
||||
switch_say_file(sh, "digits/%d", c);
|
||||
}
|
||||
} else {
|
||||
switch_say_file(sh, "digits/%d", c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (what && (a || b || c)) {
|
||||
switch_say_file(sh, what);
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t es_say_general_count(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
|
||||
{
|
||||
int in;
|
||||
int x = 0;
|
||||
int places[9] = { 0 };
|
||||
char sbuf[128] = "";
|
||||
switch_status_t status;
|
||||
|
||||
if (say_args->method == SSM_ITERATED) {
|
||||
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
|
||||
char *p;
|
||||
for (p = tosay; p && *p; p++) {
|
||||
char *n_p = p+1;
|
||||
switch_say_file(sh, "digits/%c", *p);
|
||||
if (n_p && *n_p) {
|
||||
switch_say_file(sh, "silence_stream://100");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
in = atoi(tosay);
|
||||
|
||||
if (in != 0) {
|
||||
for (x = 8; x >= 0; x--) {
|
||||
int num = (int) pow(10, x);
|
||||
if ((places[(uint32_t) x] = in / num)) {
|
||||
in -= places[(uint32_t) x] * num;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch (say_args->method) {
|
||||
case SSM_PRONOUNCED_YEAR:
|
||||
{
|
||||
int num = atoi(tosay);
|
||||
int a = num / 100;
|
||||
int b = num % 100;
|
||||
|
||||
if (!b || !(a % 10)) {
|
||||
say_num(sh, num, SSM_PRONOUNCED);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
say_num(sh, a, SSM_PRONOUNCED);
|
||||
say_num(sh, b, SSM_PRONOUNCED);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
break;
|
||||
case SSM_COUNTED:
|
||||
case SSM_PRONOUNCED:
|
||||
if ((status = play_group(SSM_PRONOUNCED, say_args->gender, places[8], places[7], places[6], "digits/million", sh)) != SWITCH_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
if ((status = play_group(SSM_PRONOUNCED, say_args->gender, places[5], places[4], places[3], "digits/thousand", sh)) != SWITCH_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
if ((status = play_group(say_args->method, say_args->gender, places[2], places[1], places[0], NULL, sh)) != SWITCH_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch_say_file(sh, "digits/0");
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t es_say_time(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
|
||||
{
|
||||
int32_t t;
|
||||
switch_time_t target = 0, target_now = 0;
|
||||
switch_time_exp_t tm, tm_now;
|
||||
uint8_t say_date = 0, say_time = 0, say_year = 0, say_month = 0, say_dow = 0, say_day = 0, say_yesterday = 0, say_today = 0;
|
||||
const char *tz = NULL;
|
||||
|
||||
tz = switch_say_file_handle_get_variable(sh, "timezone");
|
||||
|
||||
if (say_args->type == SST_TIME_MEASUREMENT) {
|
||||
int64_t hours = 0;
|
||||
int64_t minutes = 0;
|
||||
int64_t seconds = 0;
|
||||
int64_t r = 0;
|
||||
|
||||
if (strchr(tosay, ':')) {
|
||||
char *tme = strdup(tosay);
|
||||
char *p;
|
||||
|
||||
if ((p = strrchr(tme, ':'))) {
|
||||
*p++ = '\0';
|
||||
seconds = atoi(p);
|
||||
if ((p = strchr(tme, ':'))) {
|
||||
*p++ = '\0';
|
||||
minutes = atoi(p);
|
||||
hours = atoi(tme);
|
||||
} else {
|
||||
minutes = atoi(tme);
|
||||
}
|
||||
}
|
||||
free(tme);
|
||||
} else {
|
||||
if ((seconds = atol(tosay)) <= 0) {
|
||||
seconds = (int64_t) switch_epoch_time_now(NULL);
|
||||
}
|
||||
|
||||
if (seconds >= 60) {
|
||||
minutes = seconds / 60;
|
||||
r = seconds % 60;
|
||||
seconds = r;
|
||||
}
|
||||
|
||||
if (minutes >= 60) {
|
||||
hours = minutes / 60;
|
||||
r = minutes % 60;
|
||||
minutes = r;
|
||||
}
|
||||
}
|
||||
|
||||
if (hours) {
|
||||
say_num(sh, hours, SSM_PRONOUNCED);
|
||||
if (hours == 1) {
|
||||
switch_say_file(sh, "time/hour");
|
||||
} else {
|
||||
switch_say_file(sh, "time/hours");
|
||||
}
|
||||
} else {
|
||||
switch_say_file(sh, "digits/0");
|
||||
switch_say_file(sh, "time/hours");
|
||||
}
|
||||
|
||||
if (minutes) {
|
||||
say_num(sh, minutes, SSM_PRONOUNCED);
|
||||
if (minutes == 1) {
|
||||
switch_say_file(sh, "time/minute");
|
||||
} else {
|
||||
switch_say_file(sh, "time/minutes");
|
||||
}
|
||||
} else {
|
||||
switch_say_file(sh, "digits/0");
|
||||
switch_say_file(sh, "time/minutes");
|
||||
}
|
||||
|
||||
if (seconds) {
|
||||
say_num(sh, seconds, SSM_PRONOUNCED);
|
||||
if (seconds == 1) {
|
||||
switch_say_file(sh, "time/second");
|
||||
} else {
|
||||
switch_say_file(sh, "time/seconds");
|
||||
}
|
||||
} else {
|
||||
switch_say_file(sh, "digits/0");
|
||||
switch_say_file(sh, "time/seconds");
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if ((t = atol(tosay)) > 0) {
|
||||
target = switch_time_make(t, 0);
|
||||
target_now = switch_micro_time_now();
|
||||
} else {
|
||||
target = switch_micro_time_now();
|
||||
target_now = switch_micro_time_now();
|
||||
}
|
||||
|
||||
if (tz) {
|
||||
int check = atoi(tz);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Timezone is [%s]\n", tz);
|
||||
if (check) {
|
||||
switch_time_exp_tz(&tm, target, check);
|
||||
switch_time_exp_tz(&tm_now, target_now, check);
|
||||
} else {
|
||||
switch_time_exp_tz_name(tz, &tm, target);
|
||||
switch_time_exp_tz_name(tz, &tm_now, target_now);
|
||||
}
|
||||
} else {
|
||||
switch_time_exp_lt(&tm, target);
|
||||
switch_time_exp_lt(&tm_now, target_now);
|
||||
}
|
||||
|
||||
switch (say_args->type) {
|
||||
case SST_CURRENT_DATE_TIME:
|
||||
say_date = say_time = 1;
|
||||
break;
|
||||
case SST_CURRENT_DATE:
|
||||
say_date = 1;
|
||||
break;
|
||||
case SST_CURRENT_TIME:
|
||||
say_time = 1;
|
||||
break;
|
||||
case SST_SHORT_DATE_TIME:
|
||||
say_time = 1;
|
||||
//Time is in the future
|
||||
if ((tm.tm_year > tm_now.tm_year) ||
|
||||
(tm.tm_year == tm_now.tm_year && tm.tm_mon > tm_now.tm_mon) ||
|
||||
(tm.tm_year == tm_now.tm_year && tm.tm_mon == tm_now.tm_mon && tm.tm_mday > tm_now.tm_mday))
|
||||
{
|
||||
say_date = 1;
|
||||
break;
|
||||
}
|
||||
//Time is today or earlier
|
||||
if (tm.tm_year != tm_now.tm_year) {
|
||||
say_date = 1;
|
||||
break;
|
||||
}
|
||||
if (tm.tm_yday == tm_now.tm_yday) {
|
||||
say_today = 1;
|
||||
break;
|
||||
}
|
||||
if (tm.tm_yday == tm_now.tm_yday - 1) {
|
||||
say_yesterday = 1;
|
||||
break;
|
||||
}
|
||||
if (tm.tm_yday >= tm_now.tm_yday - 5) {
|
||||
say_dow = 1;
|
||||
break;
|
||||
}
|
||||
if (tm.tm_mon != tm_now.tm_mon) {
|
||||
say_month = say_day = say_dow = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
say_month = say_day = say_dow = 1;
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (say_today) {
|
||||
switch_say_file(sh, "time/today");
|
||||
}
|
||||
if (say_yesterday) {
|
||||
switch_say_file(sh, "time/yesterday");
|
||||
}
|
||||
if (say_dow) {
|
||||
switch_say_file(sh, "time/day-%d", tm.tm_wday);
|
||||
}
|
||||
|
||||
if (say_date) {
|
||||
say_year = say_month = say_day = say_dow = 1;
|
||||
say_today = say_yesterday = 0;
|
||||
}
|
||||
|
||||
if (say_day) {
|
||||
if (tm.tm_mday == 1) {
|
||||
say_num(sh, tm.tm_mday, SSM_COUNTED);
|
||||
} else {
|
||||
say_num(sh, tm.tm_mday, SSM_PRONOUNCED);
|
||||
}
|
||||
switch_say_file(sh, "time/de");
|
||||
}
|
||||
if (say_month) {
|
||||
switch_say_file(sh, "time/mon-%d", tm.tm_mon);
|
||||
}
|
||||
if (say_year) {
|
||||
switch_say_file(sh, "time/de");
|
||||
say_num(sh, tm.tm_year + 1900, SSM_PRONOUNCED_YEAR);
|
||||
}
|
||||
|
||||
if (say_time) {
|
||||
|
||||
if (say_date || say_today || say_yesterday || say_dow) {
|
||||
switch_say_file(sh, "time/at");
|
||||
}
|
||||
|
||||
|
||||
if (tm.tm_hour == 1) {
|
||||
switch_say_file(sh, "digits/1");
|
||||
switch_say_file(sh, "time/hour");
|
||||
} else {
|
||||
say_num(sh, tm.tm_hour, SSM_PRONOUNCED);
|
||||
switch_say_file(sh, "time/hours");
|
||||
}
|
||||
|
||||
if (tm.tm_min == 1) {
|
||||
switch_say_file(sh, "digits/1_1a");
|
||||
switch_say_file(sh, "time/minute");
|
||||
} else {
|
||||
say_num(sh, tm.tm_min, SSM_PRONOUNCED);
|
||||
switch_say_file(sh, "time/minutes");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t es_say_money(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
|
||||
{
|
||||
char sbuf[16] = ""; /* enough for 999,999,999,999.99 (w/o the commas or leading $) */
|
||||
char *dollars = NULL;
|
||||
char *cents = NULL;
|
||||
|
||||
if (strlen(tosay) > 15 || !switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
dollars = sbuf;
|
||||
|
||||
if ((cents = strchr(sbuf, '.'))) {
|
||||
*cents++ = '\0';
|
||||
if (strlen(cents) > 2) {
|
||||
cents[2] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/* If positive sign - skip over" */
|
||||
if (sbuf[0] == '+') {
|
||||
dollars++;
|
||||
}
|
||||
|
||||
/* If negative say "negative" */
|
||||
if (sbuf[0] == '-') {
|
||||
switch_say_file(sh, "currency/negative");
|
||||
dollars++;
|
||||
}
|
||||
|
||||
/* Say dollar amount */
|
||||
es_say_general_count(sh, dollars, say_args);
|
||||
if (atoi(dollars) == 1) {
|
||||
switch_say_file(sh, "currency/dollar");
|
||||
} else {
|
||||
switch_say_file(sh, "currency/dollars");
|
||||
}
|
||||
|
||||
/* Say cents */
|
||||
if (cents) {
|
||||
/* Say "and" */
|
||||
switch_say_file(sh, "currency/and");
|
||||
|
||||
es_say_general_count(sh, cents, say_args);
|
||||
if (atoi(cents) == 1) {
|
||||
switch_say_file(sh, "currency/cent");
|
||||
} else {
|
||||
switch_say_file(sh, "currency/cents");
|
||||
}
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t say_ip(switch_say_file_handle_t *sh,
|
||||
char *tosay,
|
||||
switch_say_args_t *say_args)
|
||||
|
||||
{
|
||||
char *a, *b, *c, *d;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
||||
if (!(a = strdup(tosay))) {
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!(b = strchr(a, '.'))) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
*b++ = '\0';
|
||||
|
||||
if (!(c = strchr(b, '.'))) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
*c++ = '\0';
|
||||
|
||||
if (!(d = strchr(c, '.'))) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
*d++ = '\0';
|
||||
|
||||
say_num(sh, atoi(a), say_args->method);
|
||||
switch_say_file(sh, "digits/dot");
|
||||
say_num(sh, atoi(b), say_args->method);
|
||||
switch_say_file(sh, "digits/dot");
|
||||
say_num(sh, atoi(c), say_args->method);
|
||||
switch_say_file(sh, "digits/dot");
|
||||
say_num(sh, atoi(d), say_args->method);
|
||||
|
||||
end:
|
||||
|
||||
free(a);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t say_telephone_number(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
|
||||
{
|
||||
int silence = 0;
|
||||
char *p;
|
||||
|
||||
for (p = tosay; !zstr(p); p++) {
|
||||
int a = tolower((int) *p);
|
||||
if (a >= '0' && a <= '9') {
|
||||
switch_say_file(sh, "digits/%c", a);
|
||||
silence = 0;
|
||||
} else if (a == '+' || (a >= 'a' && a <= 'z')) {
|
||||
switch_say_file(sh, "ascii/%d", a);
|
||||
silence = 0;
|
||||
} else if (!silence) {
|
||||
switch_say_file(sh, "silence_stream://100");
|
||||
silence = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t say_spell(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (p = tosay; p && *p; p++) {
|
||||
int a = tolower((int) *p);
|
||||
if (a >= '0' && a <= '9') {
|
||||
switch_say_file(sh, "digits/%c", a);
|
||||
} else {
|
||||
if (say_args->type == SST_NAME_SPELLED) {
|
||||
switch_say_file(sh, "ascii/%d", a);
|
||||
} else if (say_args->type == SST_NAME_PHONETIC) {
|
||||
switch_say_file(sh, "phonetic-ascii/%d", a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static switch_new_say_callback_t choose_callback(switch_say_args_t *say_args)
|
||||
{
|
||||
switch_new_say_callback_t say_cb = NULL;
|
||||
|
||||
switch (say_args->type) {
|
||||
case SST_NUMBER:
|
||||
case SST_ITEMS:
|
||||
case SST_PERSONS:
|
||||
case SST_MESSAGES:
|
||||
say_cb = es_say_general_count;
|
||||
break;
|
||||
case SST_TIME_MEASUREMENT:
|
||||
case SST_CURRENT_DATE:
|
||||
case SST_CURRENT_TIME:
|
||||
case SST_CURRENT_DATE_TIME:
|
||||
case SST_SHORT_DATE_TIME:
|
||||
say_cb = es_say_time;
|
||||
break;
|
||||
case SST_IP_ADDRESS:
|
||||
say_cb = say_ip;
|
||||
break;
|
||||
case SST_NAME_SPELLED:
|
||||
case SST_NAME_PHONETIC:
|
||||
say_cb = say_spell;
|
||||
break;
|
||||
case SST_CURRENCY:
|
||||
say_cb = es_say_money;
|
||||
break;
|
||||
case SST_TELEPHONE_NUMBER:
|
||||
say_cb = say_telephone_number;
|
||||
break;
|
||||
default:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown Say type=[%d]\n", say_args->type);
|
||||
break;
|
||||
}
|
||||
|
||||
return say_cb;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t run_callback(switch_new_say_callback_t say_cb, char *tosay, switch_say_args_t *say_args, switch_core_session_t *session, char **rstr)
|
||||
{
|
||||
switch_say_file_handle_t *sh;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
switch_event_t *var_event = NULL;
|
||||
|
||||
if (session) {
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
switch_channel_get_variables(channel, &var_event);
|
||||
}
|
||||
|
||||
switch_say_file_handle_create(&sh, say_args->ext, &var_event);
|
||||
|
||||
status = say_cb(sh, tosay, say_args);
|
||||
|
||||
if ((*rstr = switch_say_file_handle_detach_path(sh))) {
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
switch_say_file_handle_destroy(&sh);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t es_say(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
|
||||
{
|
||||
|
||||
switch_new_say_callback_t say_cb = NULL;
|
||||
char *string = NULL;
|
||||
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
||||
say_cb = choose_callback(say_args);
|
||||
|
||||
if (say_cb) {
|
||||
status = run_callback(say_cb, tosay, say_args, session, &string);
|
||||
if (session && string) {
|
||||
status = switch_ivr_play_file(session, NULL, string, args);
|
||||
}
|
||||
|
||||
switch_safe_free(string);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t es_say_string(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, char **rstr)
|
||||
{
|
||||
|
||||
switch_new_say_callback_t say_cb = NULL;
|
||||
char *string = NULL;
|
||||
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
||||
say_cb = choose_callback(say_args);
|
||||
|
||||
if (say_cb) {
|
||||
status = run_callback(say_cb, tosay, say_args, session, &string);
|
||||
if (string) {
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
*rstr = string;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_say_es_ar_load)
|
||||
{
|
||||
switch_say_interface_t *say_interface;
|
||||
/* connect my internal structure to the blank pointer passed to me */
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
say_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_SAY_INTERFACE);
|
||||
say_interface->interface_name = "es_ar";
|
||||
say_interface->say_function = es_say;
|
||||
say_interface->say_string_function = es_say_string;
|
||||
|
||||
/* indicate that the module should continue to be loaded */
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
||||
*/
|
|
@ -201,7 +201,7 @@ switch_status_t do_config()
|
|||
goto err;
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Could not find 'auth_invite' section in config file.\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Could not find 'auth_reg' section in config file.\n");
|
||||
}
|
||||
|
||||
if ((tmp = switch_xml_child(cfg, "global")) != NULL ) {
|
||||
|
@ -741,7 +741,7 @@ switch_xml_t mod_xml_radius_auth_reg(switch_event_t *params) {
|
|||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: starting registration authentication\n");
|
||||
}
|
||||
|
||||
if ( mod_xml_radius_new_handle(&new_handle, globals.auth_invite_configs) != SWITCH_STATUS_SUCCESS ) {
|
||||
if ( mod_xml_radius_new_handle(&new_handle, globals.auth_reg_configs) != SWITCH_STATUS_SUCCESS ) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to load radius handle for registration authentication\n");
|
||||
goto err;
|
||||
}
|
||||
|
@ -849,7 +849,7 @@ static switch_xml_t mod_xml_radius_directory_search(const char *section, const c
|
|||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: starting authentication\n");
|
||||
switch_event_serialize(params, &event_buf, SWITCH_TRUE);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Event: %s \n", event_buf);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Section: %s \nTag: %s\nKey_name: %s\nKey_value: %s\n",
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "\nSection: %s \nTag: %s\nKey_name: %s\nKey_value: %s\n",
|
||||
section, tag_name, key_name, key_value);
|
||||
}
|
||||
|
||||
|
@ -1087,7 +1087,7 @@ SWITCH_STANDARD_APP(radius_auth_handle)
|
|||
temp = NULL;
|
||||
|
||||
if ( result != 0 ) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Failed to authenticate\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Failed to authenticate, authentication result: %d \n", result);
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -1169,7 +1169,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_xml_radius_load)
|
|||
return SWITCH_STATUS_TERM;
|
||||
}
|
||||
|
||||
if ( globals.auth_invite_configs ) {
|
||||
if ( globals.auth_invite_configs && globals.auth_reg_configs ) {
|
||||
status = switch_xml_bind_search_function(mod_xml_radius_directory_search, switch_xml_parse_section_string("directory"), NULL);
|
||||
}
|
||||
|
||||
|
|
|
@ -4303,7 +4303,6 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t *
|
|||
switch_safe_free(substituted);
|
||||
substituted = switch_string_replace(substituted ? substituted : dtstr, replace, X);
|
||||
|
||||
printf("WTF [%s][%s]\n", replace, substituted);
|
||||
pcre_free_substring(replace);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
/*
|
||||
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
|
||||
|
@ -1300,6 +1301,12 @@ SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload)
|
|||
switch_core_hash_init(&IP_LIST.hash);
|
||||
|
||||
|
||||
tmp_name = "rfc6598.auto";
|
||||
switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);
|
||||
switch_network_list_add_cidr(rfc_list, "100.64.0.0/10", SWITCH_TRUE);
|
||||
switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
|
||||
|
||||
tmp_name = "rfc1918.auto";
|
||||
switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);
|
||||
|
@ -1327,6 +1334,7 @@ SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload)
|
|||
switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_TRUE);
|
||||
switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_TRUE);
|
||||
switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_TRUE);
|
||||
switch_network_list_add_cidr(rfc_list, "100.64.0.0/10", SWITCH_TRUE);
|
||||
switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
|
||||
|
||||
tmp_name = "loopback.auto";
|
||||
|
@ -1551,6 +1559,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_thread_set_cpu_affinity(int cpu)
|
|||
}
|
||||
|
||||
|
||||
#ifdef ENABLE_ZRTP
|
||||
static void switch_core_set_serial(void)
|
||||
{
|
||||
char buf[13] = "";
|
||||
|
@ -1596,7 +1605,7 @@ static void switch_core_set_serial(void)
|
|||
|
||||
switch_core_set_variable("switch_serial", buf);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
SWITCH_DECLARE(int) switch_core_test_flag(int flag)
|
||||
{
|
||||
|
@ -1740,8 +1749,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc
|
|||
switch_core_set_variable("certs_dir", SWITCH_GLOBAL_dirs.certs_dir);
|
||||
switch_core_set_variable("storage_dir", SWITCH_GLOBAL_dirs.storage_dir);
|
||||
switch_core_set_variable("cache_dir", SWITCH_GLOBAL_dirs.cache_dir);
|
||||
#ifdef ENABLE_ZRTP
|
||||
switch_core_set_serial();
|
||||
|
||||
#endif
|
||||
switch_console_init(runtime.memory_pool);
|
||||
switch_event_init(runtime.memory_pool);
|
||||
switch_channel_global_init(runtime.memory_pool);
|
||||
|
@ -1972,6 +1982,12 @@ static void switch_load_core_config(const char *file)
|
|||
runtime.core_db_inner_pre_trans_execute = switch_core_strdup(runtime.memory_pool, val);
|
||||
} else if (!strcasecmp(var, "core-db-inner-post-trans-execute") && !zstr(val)) {
|
||||
runtime.core_db_inner_post_trans_execute = switch_core_strdup(runtime.memory_pool, val);
|
||||
} else if (!strcasecmp(var, "dialplan-timestamps")) {
|
||||
if (switch_true(val)) {
|
||||
switch_set_flag((&runtime), SCF_DIALPLAN_TIMESTAMPS);
|
||||
} else {
|
||||
switch_clear_flag((&runtime), SCF_DIALPLAN_TIMESTAMPS);
|
||||
}
|
||||
} else if (!strcasecmp(var, "mailer-app") && !zstr(val)) {
|
||||
runtime.mailer_app = switch_core_strdup(runtime.memory_pool, val);
|
||||
} else if (!strcasecmp(var, "mailer-app-args") && val) {
|
||||
|
|
|
@ -235,7 +235,7 @@ SWITCH_DECLARE(int) switch_core_media_crypto_keylen(switch_rtp_crypto_key_type_t
|
|||
static int get_channels(const char *name, int dft)
|
||||
{
|
||||
|
||||
if (!switch_true(switch_core_get_variable("NDLB_broken_opus_sdp")) && !strcasecmp(name, "opus")) {
|
||||
if (!zstr(name) && !switch_true(switch_core_get_variable("NDLB_broken_opus_sdp")) && !strcasecmp(name, "opus")) {
|
||||
return 2; /* IKR???*/
|
||||
}
|
||||
|
||||
|
@ -3827,7 +3827,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
|
|||
switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->recv_pt);
|
||||
switch_channel_set_variable(session->channel, "rtp_audio_recv_pt", tmp);
|
||||
|
||||
if (switch_core_codec_ready(&a_engine->read_codec)) {
|
||||
if (switch_core_codec_ready(&a_engine->read_codec) && strcasecmp(matches[0].imp->iananame, a_engine->read_codec.implementation->iananame)) {
|
||||
a_engine->reset_codec = 1;
|
||||
}
|
||||
|
||||
|
@ -4071,7 +4071,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
|
|||
switch_channel_set_variable(session->channel, "rtp_video_recv_pt", tmp);
|
||||
if (!match && vmatch) match = 1;
|
||||
|
||||
if (switch_core_codec_ready(&v_engine->read_codec)) {
|
||||
if (switch_core_codec_ready(&v_engine->read_codec) && strcasecmp(matches[0].imp->iananame, v_engine->read_codec.implementation->iananame)) {
|
||||
v_engine->reset_codec = 1;
|
||||
}
|
||||
|
||||
|
@ -4375,7 +4375,10 @@ static switch_status_t start_video_thread(switch_core_session_t *session)
|
|||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "%s Starting Video thread\n", switch_core_session_get_name(session));
|
||||
|
||||
switch_rtp_set_default_payload(v_engine->rtp_session, v_engine->cur_payload_map->agreed_pt);
|
||||
if (v_engine->rtp_session) {
|
||||
switch_rtp_set_default_payload(v_engine->rtp_session, v_engine->cur_payload_map->agreed_pt);
|
||||
}
|
||||
|
||||
v_engine->mh.session = session;
|
||||
switch_threadattr_create(&thd_attr, pool);
|
||||
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
|
||||
|
@ -4388,7 +4391,10 @@ static switch_status_t start_video_thread(switch_core_session_t *session)
|
|||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_media_start_video_thread(switch_core_session_t *session)
|
||||
{
|
||||
return start_video_thread(session);
|
||||
}
|
||||
|
||||
//?
|
||||
#define RA_PTR_LEN 512
|
||||
|
@ -4940,7 +4946,13 @@ SWITCH_DECLARE(void) switch_core_session_wake_video_thread(switch_core_session_t
|
|||
|
||||
v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
|
||||
|
||||
if (!v_engine->rtp_session) {
|
||||
if ((!smh->mparams->external_video_source) && (!v_engine->rtp_session)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!v_engine->mh.cond_mutex) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Channel %s has no cond?\n",
|
||||
switch_channel_get_name(session->channel));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -2811,8 +2811,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_exec(switch_core_session_t *
|
|||
}
|
||||
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "EXECUTE %s %s(%s)\n",
|
||||
if ( switch_core_test_flag(SCF_DIALPLAN_TIMESTAMPS) ) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "EXECUTE %s %s(%s)\n",
|
||||
switch_channel_get_name(session->channel), app, switch_str_nil(expanded));
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "EXECUTE %s %s(%s)\n",
|
||||
switch_channel_get_name(session->channel), app, switch_str_nil(expanded));
|
||||
}
|
||||
|
||||
if ((var = switch_channel_get_variable(session->channel, "verbose_presence")) && switch_true(var)) {
|
||||
char *myarg = NULL;
|
||||
|
|
|
@ -1267,20 +1267,38 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_execute_sql_callback_err(switch_
|
|||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Performs test_sql and if it fails performs drop_sql and reactive_sql.
|
||||
*
|
||||
* If auto-clear-sql is disabled, then this function will do nothing and it is
|
||||
* assumed that the queries are not needed. If auto-create-schemas is disabled,
|
||||
* then just test_sql is executed, but drop_sql and reactive_sql are not.
|
||||
*
|
||||
* Otherwise, test_sql gets executed. If that succeeds, then there is nothing to
|
||||
* do. Otherwise drop_sql is executed (its result is ignored) and then finally
|
||||
* reactive_sql is executed.
|
||||
*
|
||||
* \return If auto-create-schemas is enabled, SWITCH_TRUE is returned if
|
||||
* test_sql succeeds, SWITCH_FALSE otherwise. If reactive_sql is executed
|
||||
* successfully SWITCH_TRUE is returned, otherwise SWITCH_FALSE is returned.
|
||||
*/
|
||||
SWITCH_DECLARE(switch_bool_t) switch_cache_db_test_reactive(switch_cache_db_handle_t *dbh,
|
||||
const char *test_sql, const char *drop_sql, const char *reactive_sql)
|
||||
{
|
||||
char *errmsg;
|
||||
switch_bool_t r = SWITCH_TRUE;
|
||||
switch_mutex_t *io_mutex = dbh->io_mutex;
|
||||
|
||||
switch_assert(test_sql != NULL);
|
||||
switch_assert(reactive_sql != NULL);
|
||||
|
||||
if (!switch_test_flag((&runtime), SCF_CLEAR_SQL)) {
|
||||
return SWITCH_TRUE;
|
||||
}
|
||||
|
||||
if (!switch_test_flag((&runtime), SCF_AUTO_SCHEMAS)) {
|
||||
switch_cache_db_execute_sql(dbh, (char *)test_sql, NULL);
|
||||
return SWITCH_TRUE;
|
||||
switch_status_t status = switch_cache_db_execute_sql(dbh, (char *)test_sql, NULL);
|
||||
|
||||
return (status == SWITCH_STATUS_SUCCESS) ? SWITCH_TRUE : SWITCH_FALSE;
|
||||
}
|
||||
|
||||
if (io_mutex) switch_mutex_lock(io_mutex);
|
||||
|
@ -1289,49 +1307,48 @@ SWITCH_DECLARE(switch_bool_t) switch_cache_db_test_reactive(switch_cache_db_hand
|
|||
case SCDB_TYPE_PGSQL:
|
||||
{
|
||||
if (switch_pgsql_handle_exec(dbh->native_handle.pgsql_dbh, test_sql, NULL) != SWITCH_PGSQL_SUCCESS) {
|
||||
r = SWITCH_FALSE;
|
||||
if (drop_sql) {
|
||||
switch_pgsql_handle_exec(dbh->native_handle.pgsql_dbh, drop_sql, NULL);
|
||||
}
|
||||
switch_pgsql_handle_exec(dbh->native_handle.pgsql_dbh, reactive_sql, NULL);
|
||||
r = switch_pgsql_handle_exec(dbh->native_handle.pgsql_dbh, reactive_sql, NULL) == SWITCH_PGSQL_SUCCESS;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SCDB_TYPE_ODBC:
|
||||
{
|
||||
if (switch_odbc_handle_exec(dbh->native_handle.odbc_dbh, test_sql, NULL, NULL) != SWITCH_ODBC_SUCCESS) {
|
||||
r = SWITCH_FALSE;
|
||||
if (drop_sql) {
|
||||
switch_odbc_handle_exec(dbh->native_handle.odbc_dbh, drop_sql, NULL, NULL);
|
||||
}
|
||||
switch_odbc_handle_exec(dbh->native_handle.odbc_dbh, reactive_sql, NULL, NULL);
|
||||
r = switch_odbc_handle_exec(dbh->native_handle.odbc_dbh, reactive_sql, NULL, NULL) == SWITCH_ODBC_SUCCESS;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SCDB_TYPE_CORE_DB:
|
||||
{
|
||||
if (test_sql) {
|
||||
switch_core_db_exec(dbh->native_handle.core_db_dbh, test_sql, NULL, NULL, &errmsg);
|
||||
char *errmsg = NULL;
|
||||
switch_core_db_exec(dbh->native_handle.core_db_dbh, test_sql, NULL, NULL, &errmsg);
|
||||
|
||||
if (errmsg) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL ERR [%s]\n[%s]\nAuto Generating Table!\n", errmsg, test_sql);
|
||||
switch_core_db_free(errmsg);
|
||||
errmsg = NULL;
|
||||
if (drop_sql) {
|
||||
switch_core_db_exec(dbh->native_handle.core_db_dbh, drop_sql, NULL, NULL, &errmsg);
|
||||
}
|
||||
if (errmsg) {
|
||||
r = SWITCH_FALSE;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL ERR [%s]\n[%s]\nAuto Generating Table!\n", errmsg, test_sql);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Ignoring SQL ERR [%s]\n[%s]\n", errmsg, drop_sql);
|
||||
switch_core_db_free(errmsg);
|
||||
errmsg = NULL;
|
||||
if (drop_sql) {
|
||||
switch_core_db_exec(dbh->native_handle.core_db_dbh, drop_sql, NULL, NULL, &errmsg);
|
||||
}
|
||||
if (errmsg) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL ERR [%s]\n[%s]\n", errmsg, drop_sql);
|
||||
switch_core_db_free(errmsg);
|
||||
errmsg = NULL;
|
||||
}
|
||||
switch_core_db_exec(dbh->native_handle.core_db_dbh, reactive_sql, NULL, NULL, &errmsg);
|
||||
if (errmsg) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL ERR [%s]\n[%s]\n", errmsg, reactive_sql);
|
||||
switch_core_db_free(errmsg);
|
||||
errmsg = NULL;
|
||||
}
|
||||
}
|
||||
switch_core_db_exec(dbh->native_handle.core_db_dbh, reactive_sql, NULL, NULL, &errmsg);
|
||||
if (errmsg) {
|
||||
r = SWITCH_FALSE;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL ERR [%s]\n[%s]\n", errmsg, reactive_sql);
|
||||
switch_core_db_free(errmsg);
|
||||
errmsg = NULL;
|
||||
} else {
|
||||
r = SWITCH_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1088,17 +1088,17 @@ static void send_record_stop_event(switch_channel_t *channel, switch_codec_imple
|
|||
{
|
||||
switch_event_t *event;
|
||||
|
||||
if (read_impl->actual_samples_per_second) {
|
||||
switch_channel_set_variable_printf(channel, "record_seconds", "%d", rh->fh->samples_out / read_impl->actual_samples_per_second);
|
||||
switch_channel_set_variable_printf(channel, "record_ms", "%d", rh->fh->samples_out / (read_impl->actual_samples_per_second / 1000));
|
||||
if (rh->fh) {
|
||||
switch_channel_set_variable_printf(channel, "record_samples", "%d", rh->fh->samples_out);
|
||||
if (read_impl->actual_samples_per_second) {
|
||||
switch_channel_set_variable_printf(channel, "record_seconds", "%d", rh->fh->samples_out / read_impl->actual_samples_per_second);
|
||||
switch_channel_set_variable_printf(channel, "record_ms", "%d", rh->fh->samples_out / (read_impl->actual_samples_per_second / 1000));
|
||||
}
|
||||
}
|
||||
|
||||
if (!zstr(rh->completion_cause)) {
|
||||
switch_channel_set_variable_printf(channel, "record_completion_cause", "%s", rh->completion_cause);
|
||||
}
|
||||
|
||||
switch_channel_set_variable_printf(channel, "record_samples", "%d", rh->fh->samples_out);
|
||||
|
||||
if (switch_event_create(&event, SWITCH_EVENT_RECORD_STOP) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_event_set_data(channel, event);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Record-File-Path", rh->file);
|
||||
|
|
|
@ -129,9 +129,7 @@ SWITCH_DECLARE(switch_stun_packet_t *) switch_stun_packet_parse(uint8_t *buf, ui
|
|||
packet = (switch_stun_packet_t *) buf;
|
||||
packet->header.type = ntohs(packet->header.type);
|
||||
packet->header.length = ntohs(packet->header.length);
|
||||
if (packet->header.length > (bytes_left -= 20))
|
||||
return NULL;
|
||||
|
||||
if (packet->header.length > (bytes_left -= 20)) return NULL;
|
||||
|
||||
/*
|
||||
* Check packet type (RFC3489(bis?) values)
|
||||
|
|
|
@ -2567,6 +2567,12 @@ SWITCH_DECLARE(int) switch_wait_sock(switch_os_socket_t sock, uint32_t ms, switc
|
|||
|
||||
s = poll(pfds, 1, ms);
|
||||
|
||||
if (s < 0) {
|
||||
if (switch_errno_is_break(switch_errno())) {
|
||||
s = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (s < 0) {
|
||||
r = s;
|
||||
} else if (s > 0) {
|
||||
|
@ -2645,6 +2651,12 @@ SWITCH_DECLARE(int) switch_wait_socklist(switch_waitlist_t *waitlist, uint32_t l
|
|||
|
||||
s = poll(pfds, len, ms);
|
||||
|
||||
if (s < 0) {
|
||||
if (switch_errno_is_break(switch_errno())) {
|
||||
s = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (s < 0) {
|
||||
r = s;
|
||||
} else if (s > 0) {
|
||||
|
@ -2758,6 +2770,12 @@ SWITCH_DECLARE(int) switch_wait_sock(switch_os_socket_t sock, uint32_t ms, switc
|
|||
|
||||
s = select(sock + 1, (flags & SWITCH_POLL_READ) ? rfds : NULL, (flags & SWITCH_POLL_WRITE) ? wfds : NULL, (flags & SWITCH_POLL_ERROR) ? efds : NULL, &tv);
|
||||
|
||||
if (s < 0) {
|
||||
if (switch_errno_is_break(switch_errno())) {
|
||||
s = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (s < 0) {
|
||||
r = s;
|
||||
} else if (s > 0) {
|
||||
|
@ -2858,6 +2876,12 @@ SWITCH_DECLARE(int) switch_wait_socklist(switch_waitlist_t *waitlist, uint32_t l
|
|||
|
||||
s = select(max_fd + 1, (flags & SWITCH_POLL_READ) ? rfds : NULL, (flags & SWITCH_POLL_WRITE) ? wfds : NULL, (flags & SWITCH_POLL_ERROR) ? efds : NULL, &tv);
|
||||
|
||||
if (s < 0) {
|
||||
if (switch_errno_is_break(switch_errno())) {
|
||||
s = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (s < 0) {
|
||||
r = s;
|
||||
} else if (s > 0) {
|
||||
|
|
|
@ -87,7 +87,8 @@ fi
|
|||
post_cmd=""
|
||||
command -v wget >/dev/null 2>&1
|
||||
if [ $? -eq 0 ]; then
|
||||
post_cmd="wget --output-file=/dev/null --output-document=/tmp/fscore_pb.tmp/pb_out --http-user=pastebin --http-password=freeswitch http://pastebin.freeswitch.org --post-file=$post_file"
|
||||
post_cmd="wget --output-file=/dev/null --output-document=/tmp/fscore_pb.tmp/pb_out --http-user=pastebin --http-password=freeswitch https://pastebin.freeswitch.org --post-file=$post_file"
|
||||
echo -n "paste=Send&remember=0&poster=$user&format=none&expiry=f&code2=" > $post_file
|
||||
fi
|
||||
|
||||
if [ -z "$post_cmd" ]; then
|
||||
|
@ -102,17 +103,15 @@ if [ -z "$post_cmd" ]; then
|
|||
exit 255
|
||||
fi
|
||||
|
||||
if [[ "$post_cmd" == wget* ]]; then
|
||||
echo -n "paste=Send&remember=0&poster=$user&format=none&expiry=f&code2=" > $post_file
|
||||
fi
|
||||
|
||||
echo "Gathering Data Please Wait........."
|
||||
|
||||
UNAME=`uname`;
|
||||
|
||||
#Linux
|
||||
if [ $(uname) == "Linux" ]; then
|
||||
if [ "${UNAME}" = "Linux" ]; then
|
||||
echo "LSB RELEASE:" >> $post_file
|
||||
echo $line >> $post_file
|
||||
if [ -f /etc/redhat-release ] ; then
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
cat /etc/redhat-release >> $post_file
|
||||
else
|
||||
lsb_release -a >> $post_file
|
||||
|
@ -122,7 +121,7 @@ if [ $(uname) == "Linux" ]; then
|
|||
echo $line >> $post_file
|
||||
cat /proc/cpuinfo >> $post_file
|
||||
#Mac
|
||||
elif [ $(uname) == "Darwin" ]; then
|
||||
elif [ "${UNAME}" = "Darwin" ]; then
|
||||
system_profiler SPSoftwareDataType SPHardwareDataType >> $post_file
|
||||
fi;
|
||||
|
||||
|
|
Loading…
Reference in New Issue