Merge branch 'master' into v1.4

This commit is contained in:
Ken Rice 2014-11-18 10:18:40 -06:00
commit decb35332b
100 changed files with 3693 additions and 1307 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 -->

View File

@ -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 -->

View File

@ -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"/>

View File

@ -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"/> -->

View File

@ -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 -->

View File

@ -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>

View File

@ -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"/>-->

View File

@ -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>

View File

@ -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"/> -->

View File

@ -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

2
debian/bootstrap.sh vendored
View File

@ -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

View File

@ -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.

View File

@ -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 \

1
debian/rules vendored
View File

@ -55,7 +55,6 @@ clean:
dh $@
override_dh_auto_clean:
dh_clean
.stamp-bootstrap:
@$(call show_vars)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
},

View File

@ -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 },

View File

@ -2,6 +2,9 @@
*
*
*/
#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
#endif
#define _BSD_SOURCE
#include "private/ftdm_core.h"

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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));

View File

@ -38,6 +38,9 @@
*/
#ifdef __linux__
#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
#endif
#ifndef _BSD_SOURCE
#define _BSD_SOURCE /* for strsep() */
#endif

View File

@ -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);
}

View File

@ -40,6 +40,9 @@
*
*/
#ifdef WP_DEBUG_IO
#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
#endif
#define _BSD_SOURCE
#include <syscall.h>
#endif

View File

@ -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;

View File

@ -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;

View File

@ -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 *****/

View File

@ -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;

View File

@ -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>

View File

@ -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

View File

@ -1 +1 @@
Fri Oct 31 13:48:09 CDT 2014
Wed Nov 12 13:07:56 CST 2014

View File

@ -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);
}

View File

@ -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)

View File

@ -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>

View File

@ -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>

View File

@ -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>

37
scripts/perl/mkgws.pl Normal file
View File

@ -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
}

View File

@ -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

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -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);
}
}

View File

@ -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");
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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>

View File

@ -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) {

View File

@ -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"));
}
/**

View File

@ -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);

View File

@ -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);

View File

@ -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>");

View File

@ -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

View File

@ -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 */
}
}
}
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
};

View File

@ -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)) {

View File

@ -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)),

View File

@ -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;

View File

@ -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)) {

View File

@ -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

View File

@ -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>

View File

@ -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
*/

View File

@ -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"/>

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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());

View File

@ -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,

View File

@ -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);
}

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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:
*/

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}
}
}

View File

@ -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);

View 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)

View File

@ -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) {

View File

@ -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;