Merge branch 'master' into v1.4 and bump rev

Conflicts:
	configure.ac
This commit is contained in:
Ken Rice 2014-07-15 10:33:52 -05:00
commit 59bdbecbd2
339 changed files with 33984 additions and 3013 deletions

2
.gitignore vendored
View File

@ -111,7 +111,7 @@ Release/
/libs/curl/lib/ca-bundle.h
/libs/esl/fs_cli
/libs/esl/ivrd
/libs/esl/fs_ivrd
/libs/esl/testclient
/libs/esl/testserver
/libs/freetdm/detect_dtmf

View File

@ -4132,11 +4132,13 @@ Global
{5BE9A596-F11F-4379-928C-412F81AE182B}.Debug|Win32.ActiveCfg = Debug|Win32
{5BE9A596-F11F-4379-928C-412F81AE182B}.Debug|Win32.Build.0 = Debug|Win32
{5BE9A596-F11F-4379-928C-412F81AE182B}.Debug|x64.ActiveCfg = Debug|Win32
{5BE9A596-F11F-4379-928C-412F81AE182B}.Debug|x64.Build.0 = Debug|Win32
{5BE9A596-F11F-4379-928C-412F81AE182B}.Debug|x64 Setup.ActiveCfg = Debug|Win32
{5BE9A596-F11F-4379-928C-412F81AE182B}.Debug|x86 Setup.ActiveCfg = Debug|Win32
{5BE9A596-F11F-4379-928C-412F81AE182B}.Release|Win32.ActiveCfg = Release|Win32
{5BE9A596-F11F-4379-928C-412F81AE182B}.Release|Win32.Build.0 = Release|Win32
{5BE9A596-F11F-4379-928C-412F81AE182B}.Release|x64.ActiveCfg = Release|Win32
{5BE9A596-F11F-4379-928C-412F81AE182B}.Release|x64.Build.0 = Release|Win32
{5BE9A596-F11F-4379-928C-412F81AE182B}.Release|x64 Setup.ActiveCfg = Release|Win32
{5BE9A596-F11F-4379-928C-412F81AE182B}.Release|x86 Setup.ActiveCfg = Release|Win32
EndGlobalSection

View File

@ -644,7 +644,9 @@ pa-reconf:
srtp-reconf:
cd libs/srtp && $(MAKE) clean
cd libs/srtp && sh ./configure.gnu
cd libs/srtp && sh ./config.status --recheck
cd libs/srtp && sh ./config.status
iks-reconf:
cd libs/iksemel && $(MAKE) clean

View File

@ -9,13 +9,14 @@
#
FSPREFIX=/usr/local/freeswitch
PREFIX=/opt/fs-libs
DOWNLOAD=http://files.freeswitch.org/downloads/libs
JPEG=v8d
OPENSSL=1.0.1g
OPENSSL=1.0.1h
SQLITE=autoconf-3080403
PCRE=8.35
CURL=7.36.0
CURL=7.35.0
SPEEX=1.2rc1
LIBEDIT=20140213-3.1
LIBEDIT=20140618-3.1
LDNS=1.6.17
freeswitch: deps has-git freeswitch.git/Makefile
@ -33,60 +34,66 @@ freeswitch.git/bootstrap.sh: has-git
install: freeswitch
cd freeswitch.git && make install
install-git:
rpm -i http://apt.sw.be/redhat/el5/en/x86_64/rpmforge/RPMS//rpmforge-release-0.3.6-1.el5.rf.x86_64.rpm
install-git: .done
.done:
rpm -i http://apt.sw.be/redhat/el5/en/x86_64/rpmforge/RPMS/rpmforge-release-0.3.6-1.el5.rf.x86_64.rpm || true
yum update -y
yum install -y git gcc-c++ wget ncurses-devel zlib-devel e2fsprogs-devel libtool automake autoconf
touch .done
has-git:
has-git:
@git --version || (echo "please install git by running 'make install-git'" && false)
libjpeg: jpeg-8d/Makefile
clean:
@rm -rf openssl* ldns* jpeg* pcre* perl* pkg-config* speex* sqlite* libedit* curl* *~
(cd freeswitch.git && git clean -fdx && git reset --hard HEAD && git pull)
jpeg-8d/Makefile:
(test -d jpeg-8d) || (wget -4 -O jpegsrc.$(JPEG).tar.gz http://www.ijg.org/files/jpegsrc.$(JPEG).tar.gz && tar zxfv jpegsrc.$(JPEG).tar.gz)
(cd jpeg-8d && ./configure --prefix=$(PREFIX) && make && sudo make install)
libjpeg: jpeg-8d/.done
openssl: openssl-$(OPENSSL)
jpeg-8d/.done:
(test -d jpeg-8d) || (wget -4 -O jpegsrc.$(JPEG).tar.gz $(DOWNLOAD)/jpegsrc.$(JPEG).tar.gz && tar zxfv jpegsrc.$(JPEG).tar.gz)
(cd jpeg-8d && ./configure --prefix=$(PREFIX) && make && sudo make install && touch .done)
openssl: openssl-$(OPENSSL)/.done
openssl-$(OPENSSL)/.done: openssl-$(OPENSSL)
openssl-$(OPENSSL):
(test -d $@) || (wget -4 -O $@.tar.gz http://www.openssl.org/source/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && ./Configure --prefix=$(PREFIX) linux-x86_64 shared && make && sudo make install)
sqlite: sqlite-$(SQLITE)
(test -d $@) || (wget -4 -O $@.tar.gz $(DOWNLOAD)/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && ./Configure --prefix=$(PREFIX) linux-x86_64 shared && make && sudo make install && touch .done)
sqlite: sqlite-$(SQLITE)/.done
sqlite-$(SQLITE)/.done: sqlite-$(SQLITE)
sqlite-$(SQLITE):
(test -d $@) || (wget -4 -O $@.tar.gz http://www.sqlite.org/2014/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && ./configure --prefix=$(PREFIX) && make && sudo make install)
pcre: pcre-$(PCRE)
(test -d $@) || (wget -4 -O $@.tar.gz $(DOWNLOAD)/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && ./configure --prefix=$(PREFIX) && make && sudo make install && touch .done_sqlite && touch .done)
pcre: pcre-$(PCRE)/.done
pcre-$(PCRE)/.done: pcre-$(PCRE)
pcre-$(PCRE):
(test -d $@) || (wget -4 -O $@.tar.gz http://downloads.sourceforge.net/project/pcre/pcre/$(PCRE)/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && ./configure --prefix=$(PREFIX) && make && sudo make install)
curl: curl-$(CURL)
(test -d $@) || (wget -4 -O $@.tar.gz $(DOWNLOAD)/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && ./configure --prefix=$(PREFIX) && make && sudo make install && touch .done)
curl: curl-$(CURL)/.done
curl-$(CURL)/.done: curl-$(CURL)
curl-$(CURL):
(test -d $@) || (wget -4 -O $@.tar.gz http://curl.haxx.se/download/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && ./configure --prefix=$(PREFIX) && make && sudo make install)
speex: speex-$(SPEEX)
(test -d $@) || (wget -4 -O $@.tar.gz $(DOWNLOAD)/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && ./configure --prefix=$(PREFIX) && make && sudo make install && touch .done)
speex: speex-$(SPEEX)/.done
speex-$(SPEEX)/.done: speex-$(SPEEX)
speex-$(SPEEX):
(test -d $@) || (wget -4 -O $@.tar.gz http://downloads.xiph.org/releases/speex/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && ./configure --prefix=$(PREFIX) && make && sudo make install)
libedit: libedit-$(LIBEDIT)
(test -d $@) || (wget -4 -O $@.tar.gz $(DOWNLOAD)/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && ./configure --prefix=$(PREFIX) && make && sudo make install && touch .done)
libedit: libedit-$(LIBEDIT)/.done
libedit-$(LIBEDIT)/.done: libedit-$(LIBEDIT)
libedit-$(LIBEDIT):
(test -d $@) || (wget -4 -O $@.tar.gz http://thrysoee.dk/editline/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && ./configure --prefix=$(PREFIX) && make && sudo make install)
(test -d $@) || (wget -4 -O $@.tar.gz $(DOWNLOAD)/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && ./configure --prefix=$(PREFIX) && make && sudo make install && touch .done)
ldns: ldns-$(LDNS)
ldns-$(LDNS): openssl
(test -d $@) || (wget -4 -O $@.tar.gz http://www.nlnetlabs.nl/downloads/ldns/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && ./configure --with-ssl=$(PREFIX) --prefix=$(PREFIX) && make && sudo make install)
ldns: ldns-$(LDNS)/.done
ldns-$(LDNS)/.done: ldns-$(LDNS)
ldns-$(LDNS):
(test -d $@) || (wget -4 -O $@.tar.gz $(DOWNLOAD)/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && ./configure --with-ssl=$(PREFIX) --prefix=$(PREFIX) && make && sudo make install && touch .done)
deps: libjpeg openssl sqlite pcre curl speex libedit ldns

110
build/Makefile.solaris11 Normal file
View File

@ -0,0 +1,110 @@
#
# FreeSWITCH auto-build Makefile (Solaris 11.1 64bit Tonka Truck Edition)
# http://www.freeswitch.org
# put this file anywhere and type gmake to
# create a fully-built freeswitch.git from scratch
# in that same directory.
#
#
FSPREFIX=/usr/local/freeswitch
PREFIX=/usr/local/
DOWNLOAD=http://files.freeswitch.org/downloads/libs
JP=v8d
SSL=1.0.1h
SQLITE=autoconf-3080403
PCRE=8.35
CURL=7.35.0
SPEEX=1.2rc1
LIBEDIT=20140618-3.1
LDNS=1.6.17
PKGCFG=0.28
PERL=5.18.2
freeswitch: deps has-git freeswitch.git/Makefile
cd freeswitch.git && gmake
freeswitch.git/Makefile: freeswitch.git/configure
export PATH=$PATH:$(PREFIX)/bin
cd freeswitch.git && PKG_CONFIG_PATH=$(PREFIX)/lib/pkgconfig ./configure --enable-64 LDFLAGS='-L$(PREFIX)/lib -Wl,-rpath=$(PREFIX)/lib' CFLAGS='-I$(PREFIX)/include' --prefix=$(FSPREFIX)
freeswitch.git/configure: freeswitch.git/bootstrap.sh
cd freeswitch.git && sh bootstrap.sh
freeswitch.git/bootstrap.sh: has-git
test -d freeswitch.git || git clone git://git.freeswitch.org/freeswitch.git freeswitch.git
install: freeswitch
cd freeswitch.git && gmake install
install-git:
pkg install git autoconf automake libtool libjpeg gcc-45 wget
has-git:
@git --version || (echo "please install git by running 'gmake install-git'" && false)
clean:
@rm -rf openssl* ldns* jpeg* pcre* perl* pkg-config* speex* sqlite* libedit* curl* *~
(cd freeswitch.git && git clean -fdx && git reset --hard HEAD && git pull)
libjpeg: jpeg-8d/.done
jpeg-8d/.done:
(test -d jpeg-8d) || (wget -4 -O jpegsrc.$(JP).tar.gz $(DOWNLOAD)/jpegsrc.$(JP).tar.gz && tar zxfv jpegsrc.$(JP).tar.gz)
(cd jpeg-8d && CFLAGS=-m64 LDFLAGS=-m64 ./configure --prefix=$(PREFIX) && gmake && sudo gmake install && touch .done)
openssl: openssl-$(SSL)/.done
openssl-$(SSL)/.done: openssl-$(SSL)
openssl-$(SSL):
(test -d $@) || (wget -4 -O $@.tar.gz $(DOWNLOAD)/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && CFLAGS=-m64 LDFLAGS=-m64 ./Configure --prefix=$(PREFIX) solaris64-x86_64-gcc shared && gmake && sudo gmake install && touch .done)
sqlite: sqlite-$(SQLITE)/.done
sqlite-$(SQLITE)/.done: sqlite-$(SQLITE)
sqlite-$(SQLITE):
(test -d $@) || (wget -4 -O $@.tar.gz $(DOWNLOAD)/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && CFLAGS=-m64 LDFLAGS=-m64 ./configure --prefix=$(PREFIX) && gmake && sudo gmake install && touch .done)
pcre: pcre-$(PCRE)/.done
pcre-$(PCRE)/.done: pcre-$(PCRE)
pcre-$(PCRE):
(test -d $@) || (wget -4 -O $@.tar.gz $(DOWNLOAD)/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && CXXFLAGS=-m64 CFLAGS=-m64 LDFLAGS=-m64 ./configure --prefix=$(PREFIX) && gmake && sudo gmake install && touch .done)
curl: curl-$(CURL)/.done
curl-$(CURL)/.done: curl-$(CURL)
curl-$(CURL):
(test -d $@) || (wget -4 -O $@.tar.gz $(DOWNLOAD)/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && CFLAGS=-m64 LDFLAGS=-m64 ./configure --prefix=$(PREFIX) && gmake && sudo gmake install && touch .done)
speex: speex-$(SPEEX)/.done
speex-$(SPEEX)/.done: speex-$(SPEEX)
speex-$(SPEEX):
(test -d $@) || (wget -4 -O $@.tar.gz $(DOWNLOAD)/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && CFLAGS=-m64 LDFLAGS=-m64 ./configure --prefix=$(PREFIX) && gmake && sudo gmake install && touch .done)
libedit: libedit-$(LIBEDIT)/.done
libedit-$(LIBEDIT)/.done: libedit-$(LIBEDIT)
libedit-$(LIBEDIT):
(test -d $@) || (wget -4 -O $@.tar.gz $(DOWNLOAD)/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && CFLAGS=-m64 LDFLAGS=-m64 ./configure --prefix=$(PREFIX) && gmake && sudo gmake install && touch .done)
ldns: openssl ldns-$(LDNS)/.done
ldns-$(LDNS)/.done: ldns-$(LDNS)
ldns-$(LDNS):
(test -d $@) || (wget -4 -O $@.tar.gz $(DOWNLOAD)/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && CFLAGS=-m64 LDFLAGS=-m64 ./configure --with-ssl=$(PREFIX) --prefix=$(PREFIX) && gmake && sudo gmake install && touch .done)
pkg-config: openssl pkg-config-$(PKGCFG)/.done
pkg-config-$(PKGCFG)/.done: pkg-config-$(PKGCFG)
pkg-config-$(PKGCFG):
(test -d $@) || (wget -4 -O $@.tar.gz $(DOWNLOAD)/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && CFLAGS=-m64 LDFLAGS=-m64 ./configure --with-internal-glib --prefix=$(PREFIX) && sudo gmake uninstall && gmake && sudo gmake install && \
touch .done)
perl: openssl perl-$(PERL)/.done
perl-$(PERL)/.done: perl-$(PERL)
perl-$(PERL):
(test -d $@) || (wget -4 -O $@.tar.gz $(DOWNLOAD)/$@.tar.gz && tar zxfv $@.tar.gz)
(cd $@ && CFLAGS=-m64 LDFLAGS=-m64 ./configure.gnu -Dcc=gcc --prefix=$(PREFIX) && gmake && sudo gmake install && touch .done)
deps: has-git libjpeg openssl sqlite pcre curl speex libedit ldns pkg-config perl

View File

@ -15,14 +15,14 @@ echo
here=`pwd`
cd $mods
files=`ls *.dylib *.so 2>/dev/null`
files=`ls *.so 2>/dev/null`
cd $here
for i in $files ; do
mod=${i%%.*}
infile=`grep ^.*$mod\$ ../modules.conf`
commented=`grep ^\#.*$mod\$ ../modules.conf`
infile=`grep ^.*$mod\$ ../modules.conf | grep -v ftmod_`
commented=`grep ^\#.*$mod\$ ../modules.conf | grep -v ftmod_`
if [ -z "$infile" ] ; then
echo "${on}WARNING: installed module: $i was not installed by this build. It is not present in modules.conf.${off}"

View File

@ -83,6 +83,7 @@ dialplans/mod_dialplan_xml
#endpoints/mod_h323
#endpoints/mod_khomp
endpoints/mod_rtc
endpoints/mod_verto
endpoints/mod_loopback
#endpoints/mod_opal
#endpoints/mod_portaudio

View File

@ -1,8 +0,0 @@
<configuration name="spidermonkey.conf" description="Spider Monkey JavaScript Plug-Ins">
<modules>
<load module="mod_spidermonkey_teletone"/>
<load module="mod_spidermonkey_core_db"/>
<load module="mod_spidermonkey_socket"/>
<!--<load module="mod_spidermonkey_odbc"/>-->
</modules>
</configuration>

View File

@ -1,8 +0,0 @@
<configuration name="spidermonkey.conf" description="Spider Monkey JavaScript Plug-Ins">
<modules>
<load module="mod_spidermonkey_teletone"/>
<load module="mod_spidermonkey_core_db"/>
<load module="mod_spidermonkey_socket"/>
<!--<load module="mod_spidermonkey_odbc"/>-->
</modules>
</configuration>

View File

@ -0,0 +1,27 @@
<configuration name="verto.conf" description="HTML5 Verto Endpoint">
<settings>
<param name="debug" value="0"/>
</settings>
<profiles>
<profile name="mine">
<param name="bind-local" value="0.0.0.0:8081"/>
<param name="bind-local" value="0.0.0.0:8082" secure="true"/>
<param name="secure-combined" value="/usr/local/freeswitch/certs/wss.pem"/>
<param name="secure-chain" value="/usr/local/freeswitch/certs/wss.pem"/>
<param name="userauth" value="true"/>
<param name="mcast-ip" value="224.1.1.1"/>
<param name="mcast-port" value="1337"/>
<param name="rtp-ip" value="$${local_ip_v4}"/>
<!-- <param name="ext-rtp-ip" value=""/> -->
<param name="local-network" value="localnet.auto"/>
<param name="outbound-codec-string" value="opus,vp8"/>
<param name="inbound-codec-string" value="opus,vp8"/>
<param name="apply-candidate-acl" value="wan.auto"/>
<param name="timer-name" value="soft"/>
</profile>
</profiles>
</configuration>

View File

@ -126,6 +126,14 @@
<condition field="${call_debug}" expression="^true$" break="never">
<action application="info"/>
</condition>
<condition field="${default_password}" expression="^1234$" break="never">
<action application="log" data="CRIT WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING "/>
<action application="log" data="CRIT Open ${base_dir}/conf/vars.xml and change the default_password."/>
<action application="log" data="CRIT Once changed type 'reloadxml' at the console."/>
<action application="log" data="CRIT WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING "/>
<action application="sleep" data="10000"/>
</condition>
<!--
This is an example of how to auto detect if telephone-event is missing and activate inband detection
-->

View File

@ -7,17 +7,17 @@
The special applications:
- skinny-process tells skinny to process the call (route, set call forwarding, ...)
- skinny-drop tells skinny to drop the call
- skinny-wait tells skinny to wait for more digits
- skinny-wait tells skinny to wait 'data' seconds for more numbers before drop
-->
<!-- http://wiki.freeswitch.org/wiki/Mod_skinny -->
<include>
<context name="skinny-patterns">
<!--
Wait for another digit by default
Wait 10 seconds for another digit by default, if data not specified, uses profile default
-->
<extension name="Default">
<condition>
<action application="skinny-wait" />
<action application="skinny-wait" data="10"/>
</condition>
</extension>

View File

@ -0,0 +1,96 @@
<profile name="external-ipv6">
<!-- http://wiki.freeswitch.org/wiki/Sofia_Configuration_Files -->
<!-- This profile is only for outbound registrations to providers -->
<gateways>
<X-PRE-PROCESS cmd="include" data="external/*.xml"/>
</gateways>
<aliases>
<!--
<alias name="outbound"/>
<alias name="nat"/>
-->
</aliases>
<domains>
<domain name="all" alias="false" parse="true"/>
</domains>
<settings>
<param name="debug" value="0"/>
<!-- If you want FreeSWITCH to shutdown if this profile fails to load, uncomment the next line. -->
<!-- <param name="shutdown-on-fail" value="true"/> -->
<param name="sip-trace" value="no"/>
<param name="sip-capture" value="no"/>
<param name="rfc2833-pt" value="101"/>
<!-- RFC 5626 : Send reg-id and sip.instance -->
<!--<param name="enable-rfc-5626" value="true"/> -->
<param name="sip-port" value="$${external_sip_port}"/>
<param name="dialplan" value="XML"/>
<param name="context" value="public"/>
<param name="dtmf-duration" value="2000"/>
<param name="inbound-codec-prefs" value="$${global_codec_prefs}"/>
<param name="outbound-codec-prefs" value="$${outbound_codec_prefs}"/>
<param name="hold-music" value="$${hold_music}"/>
<param name="rtp-timer-name" value="soft"/>
<!--<param name="enable-100rel" value="true"/>-->
<!--<param name="disable-srv503" value="true"/>-->
<!-- This could be set to "passive" -->
<param name="local-network-acl" value="localnet.auto"/>
<param name="manage-presence" value="false"/>
<!-- used to share presence info across sofia profiles
manage-presence needs to be set to passive on this profile
if you want it to behave as if it were the internal profile
for presence.
-->
<!-- Name of the db to use for this profile -->
<!--<param name="dbname" value="share_presence"/>-->
<!--<param name="presence-hosts" value="$${domain}"/>-->
<!--<param name="force-register-domain" value="$${domain}"/>-->
<!--all inbound reg will stored in the db using this domain -->
<!--<param name="force-register-db-domain" value="$${domain}"/>-->
<!-- ************************************************* -->
<!--<param name="aggressive-nat-detection" value="true"/>-->
<param name="inbound-codec-negotiation" value="generous"/>
<param name="nonce-ttl" value="60"/>
<param name="auth-calls" value="false"/>
<param name="inbound-late-negotiation" value="true"/>
<param name="inbound-zrtp-passthru" value="true"/> <!-- (also enables late negotiation) -->
<!--
DO NOT USE HOSTNAMES, ONLY IP ADDRESSES IN THESE SETTINGS!
-->
<param name="rtp-ip" value="$${local_ip_v6}"/>
<param name="sip-ip" value="$${local_ip_v6}"/>
<param name="ext-rtp-ip" value="auto-nat"/>
<param name="ext-sip-ip" value="auto-nat"/>
<param name="rtp-timeout-sec" value="300"/>
<param name="rtp-hold-timeout-sec" value="1800"/>
<!--<param name="enable-3pcc" value="true"/>-->
<!-- TLS: disabled by default, set to "true" to enable -->
<param name="tls" value="$${external_ssl_enable}"/>
<!-- Set to true to not bind on the normal sip-port but only on the TLS port -->
<param name="tls-only" value="false"/>
<!-- additional bind parameters for TLS -->
<param name="tls-bind-params" value="transport=tls"/>
<!-- Port to listen on for TLS requests. (5081 will be used if unspecified) -->
<param name="tls-sip-port" value="$${external_tls_port}"/>
<!-- Location of the agent.pem and cafile.pem ssl certificates (needed for TLS server) -->
<!--<param name="tls-cert-dir" value=""/>-->
<!-- Optionally set the passphrase password used by openSSL to encrypt/decrypt TLS private key files -->
<param name="tls-passphrase" value=""/>
<!-- Verify the date on TLS certificates -->
<param name="tls-verify-date" value="true"/>
<!-- TLS verify policy, when registering/inviting gateways with other servers (outbound) or handling inbound registration/invite requests how should we verify their certificate -->
<!-- set to 'in' to only verify incoming connections, 'out' to only verify outgoing connections, 'all' to verify all connections, also 'in_subjects', 'out_subjects' and 'all_subjects' for subject validation. Multiple policies can be split with a '|' pipe -->
<param name="tls-verify-policy" value="none"/>
<!-- Certificate max verify depth to use for validating peer TLS certificates when the verify policy is not none -->
<param name="tls-verify-depth" value="2"/>
<!-- If the tls-verify-policy is set to subjects_all or subjects_in this sets which subjects are allowed, multiple subjects can be split with a '|' pipe -->
<param name="tls-verify-in-subjects" value=""/>
<!-- TLS version ("sslv23" (default), "tlsv1"). NOTE: Phones may not work with TLSv1 -->
<param name="tls-version" value="$${sip_tls_version}"/>
</settings>
</profile>

View File

@ -12,6 +12,9 @@
<param name="odbc-dsn" value=""/>
<param name="debug" value="4"/>
<param name="auto-restart" value="true"/>
<!-- timeout to wait for another digit in milliseconds -->
<param name="digit-timeout" value="10000"/>
</settings>
<soft-key-set-sets>
<soft-key-set-set name="default">

View File

@ -3,10 +3,10 @@
# Must change all of the below together
# For a release, set revision for that tagged release as well and uncomment
AC_INIT([freeswitch], [1.4.6], bugs@freeswitch.org)
AC_INIT([freeswitch], [1.4.7], bugs@freeswitch.org)
AC_SUBST(SWITCH_VERSION_MAJOR, [1])
AC_SUBST(SWITCH_VERSION_MINOR, [4])
AC_SUBST(SWITCH_VERSION_MICRO, [6])
AC_SUBST(SWITCH_VERSION_MICRO, [7])
AC_SUBST(SWITCH_VERSION_REVISION, [])
AC_SUBST(SWITCH_VERSION_REVISION_HUMAN, [])
@ -493,6 +493,10 @@ AC_ARG_ENABLE(srtp,
AM_CONDITIONAL([ENABLE_SRTP],[test "${enable_srtp}" = "yes"])
have_openal=no
AC_CHECK_LIB(openal, alMidiGainSOFT, [have_openal="yes"])
AM_CONDITIONAL([HAVE_OPENAL],[test "${have_openal}" = "yes"])
AC_ARG_ENABLE(zrtp,
[AS_HELP_STRING([--enable-zrtp], [Compile with zrtp Support])],,[enable_zrtp="no"])
if test "x$enable_zrtp" = "xyes" ; then
@ -1230,16 +1234,29 @@ AM_CONDITIONAL([HAVE_MYSQL],[test "$found_mysql" = "yes"])
#
AC_CHECK_PROG(PERL,perl,[ac_cv_have_perl=yes],[ac_cv_have_perl=no])
AM_CONDITIONAL([HAVE_PERL],[test "x$ac_cv_have_perl" != "xno"])
if test "x$ac_cv_have_perl" != "xno" ; then
# -a "x$ac_cv_have_EXTERN_h" != "xno"
if test "x$ac_cv_have_perl" != "xno"; then
PERL=perl
PERL_SITEDIR="`$PERL -MConfig -e 'print $Config{sitelibexp}'`"
PERL_SITEDIR="`$PERL -MConfig -e 'print $Config{archlib}'`"
PERL_LIBDIR="-L`$PERL -MConfig -e 'print $Config{archlib}'`/CORE"
PERL_LIBS="`$PERL -MConfig -e 'print $Config{libs}'`"
PERL_CFLAGS="-w -DMULTIPLICITY `$PERL -MExtUtils::Embed -e ccopts` -DEMBED_PERL"
PERL_LDFLAGS="`$PERL -MExtUtils::Embed -e ldopts` `$PERL -MConfig -e 'print $Config{libs}'`"
PERL_CFLAGS="-w -DMULTIPLICITY `$PERL -MExtUtils::Embed -e ccopts | sed -e 's|-arch x86_64 -arch i386||'` -DEMBED_PERL"
PERL_LDFLAGS="`$PERL -MExtUtils::Embed -e ldopts| sed -e 's|-arch x86_64 -arch i386||'`"
PERL_INC="`$PERL -MExtUtils::Embed -e perl_inc`"
save_CFLAGS="$CFLAGS"
CFLAGS="$PERL_CFLAGS"
AC_CHECK_HEADER([EXTERN.h], [ac_cv_have_EXTERN_h=yes], [ac_cv_have_EXTERN_h=no], [[#include <EXTERN.h>
# include <perl.h>]])
CFLAGS="$save_CFLAGS"
save_LDFLAGS="$LDFLAGS"
LDFLAGS="$PERL_LDFLAGS"
AC_CHECK_LIB([perl], [perl_alloc], ac_cv_use_libperl=yes, ac_cv_use_libperl=no)
LDFLAGS="$save_LDFLAGS"
AC_SUBST(PERL_SITEDIR)
AC_SUBST(PERL_LIBDIR)
AC_SUBST(PERL_LIBS)
@ -1248,6 +1265,8 @@ if test "x$ac_cv_have_perl" != "xno" ; then
AC_SUBST(PERL_INC)
fi
AM_CONDITIONAL([HAVE_PERL],[test "x$ac_cv_have_perl" != "xno" -a "x$ac_cv_have_EXTERN_h" != "xno" -a "x$ac_cv_use_libperl" != "xno"])
#
# php checks
#
@ -1500,6 +1519,7 @@ AC_CONFIG_FILES([Makefile
src/mod/endpoints/mod_sofia/Makefile
src/mod/endpoints/mod_unicall/Makefile
src/mod/endpoints/mod_rtc/Makefile
src/mod/endpoints/mod_verto/Makefile
src/mod/event_handlers/mod_cdr_csv/Makefile
src/mod/event_handlers/mod_cdr_mongodb/Makefile
src/mod/event_handlers/mod_cdr_pg_csv/Makefile

17
debian/bootstrap.sh vendored
View File

@ -28,7 +28,6 @@ avoid_mods=(
endpoints/mod_reference
endpoints/mod_unicall
languages/mod_managed
languages/mod_perl
sdk/autotools
xml_int/mod_xml_ldap
xml_int/mod_xml_radius
@ -69,6 +68,7 @@ freeswitch-init
freeswitch-sysvinit
freeswitch-systemd
freeswitch-lang
freeswitch-timezones
)
err () {
@ -361,6 +361,7 @@ Recommends:
freeswitch-mod-commands (= \${binary:Version}),
freeswitch-init (= \${binary:Version}),
freeswitch-lang (= \${binary:Version}),
freeswitch-timezones (= \${binary:Version}),
freeswitch-music,
freeswitch-sounds
Suggests:
@ -394,6 +395,7 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
Recommends:
freeswitch-init (= \${binary:Version}),
freeswitch-lang (= \${binary:Version}),
freeswitch-timezones (= \${binary:Version}),
freeswitch-meta-codecs (= \${binary:Version}),
freeswitch-music,
freeswitch-sounds
@ -449,6 +451,7 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
Recommends:
freeswitch-init (= \${binary:Version}),
freeswitch-lang (= \${binary:Version}),
freeswitch-timezones (= \${binary:Version}),
freeswitch-music,
freeswitch-sounds,
freeswitch-conf-vanilla (= \${binary:Version}),
@ -464,6 +467,7 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
Recommends:
freeswitch-init (= \${binary:Version}),
freeswitch-lang (= \${binary:Version}),
freeswitch-timezones (= \${binary:Version}),
freeswitch-meta-codecs (= \${binary:Version}),
freeswitch-music,
freeswitch-sounds,
@ -547,6 +551,7 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
Recommends:
freeswitch-init (= \${binary:Version}),
freeswitch-lang (= \${binary:Version}),
freeswitch-timezones (= \${binary:Version}),
freeswitch-meta-codecs (= \${binary:Version}),
freeswitch-meta-conf (= \${binary:Version}),
freeswitch-meta-lang (= \${binary:Version}),
@ -833,6 +838,16 @@ Description: Language files for FreeSWITCH
This is a metapackage which depends on the default language packages
for FreeSWITCH.
## timezones
Package: freeswitch-timezones
Architecture: all
Depends: \${misc:Depends}
Description: Timezone files for FreeSWITCH
$(debian_wrap "${fs_description}")
.
$(debian_wrap "This package includes the timezone files for FreeSWITCH.")
EOF
}

View File

@ -411,6 +411,10 @@ Module: endpoints/mod_reference
Description: mod_reference
Adds mod_reference.
Module: endpoints/mod_rtc
Description: Adds mod_rtc.
Adds mod_rtc.
Module: endpoints/mod_rtmp
Description: mod_rtmp
Adds mod_rtmp.
@ -432,6 +436,11 @@ Module: endpoints/mod_unicall
Description: mod_unicall
Adds mod_unicall.
Module: endpoints/mod_verto
Description: Adds mod_verto.
Adds mod_verto.
Build-Depends: libperl-dev
## mod/event_handlers
Module: event_handlers/mod_cdr_csv
@ -584,14 +593,14 @@ Module: loggers/mod_console
Description: mod_console
Adds mod_console.
Module: loggers/mod_logfile
Description: mod_logfile
Adds mod_logfile.
Module: loggers/mod_graylog2
Description: mod_graylog2
Adds mod_greylog2.
Module: loggers/mod_logfile
Description: mod_logfile
Adds mod_logfile.
Module: loggers/mod_syslog
Description: mod_syslog
Adds mod_syslog.

View File

@ -11,7 +11,7 @@ PIDFile=/run/freeswitch/freeswitch.pid
PermissionsStartOnly=true
ExecStartPre=/bin/mkdir -p /run/freeswitch
ExecStartPre=/bin/chown freeswitch:freeswitch /run/freeswitch
ExecStart=/usr/bin/freeswitch -nc -nonat
ExecStart=/usr/bin/freeswitch -ncwait -nonat
TimeoutSec=45s
Restart=always
; exec

View File

@ -1,2 +1,2 @@
# /etc/default/freeswitch
DAEMON_OPTS="-rp -nonat"
DAEMON_OPTS="-nonat"

View File

@ -18,9 +18,9 @@ PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC=freeswitch
NAME=freeswitch
DAEMON=/usr/bin/freeswitch
DAEMON_ARGS="-u freeswitch -g freeswitch -nc"
USER=freeswitch
GROUP=freeswitch
DAEMON_ARGS="-u $USER -g $GROUP -ncwait"
CONFDIR=/etc/$NAME
RUNDIR=/var/run/$NAME
PIDFILE=$RUNDIR/$NAME.pid

1
debian/freeswitch-timezones.install vendored Normal file
View File

@ -0,0 +1 @@
conf/vanilla/autoload_configs/timezones.conf.xml /usr/share/freeswitch/tz

11
debian/util.sh vendored
View File

@ -295,12 +295,15 @@ build_debs () {
}
if ! [ -d $cow_img ]; then
announce "Creating base $distro-$arch image..."
cow --create
local x=30
while ! cow --create; do
[ $x -lt 1 ] && break; sleep 120; x=$((x-1))
done
fi
announce "Updating base $distro-$arch image..."
local x=5
while ! cow --update; do
[ $x -lt 1 ] && break; sleep 60; x=$((x-1))
local x=30
while ! cow --update --override-config; do
[ $x -lt 1 ] && break; sleep 120; x=$((x-1))
done
announce "Building $distro-$arch DEBs from $dsc..."
if $debug_hook; then

View File

@ -77,7 +77,7 @@ message might look like this:
> After appropriate amounts of frobbing have been done, a new variable
> `frobbing_done` is set in the caller's channel.
>
> FS-XXXX --resolve
> FS-XXXX #resolve
Patches Related to JIRA Issues
------------------------------

View File

@ -1,7 +1,7 @@
######################################################################################################################
#
# freeswitch-config-rayo for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
# Copyright (C) 2013, Grasshopper
# Copyright (C) 2013-2014, Grasshopper
#
# Version: MPL 1.1
#
@ -75,7 +75,7 @@ Group: System/Libraries
Packager: Chris Rienzo
URL: http://www.freeswitch.org/
Source0: freeswitch-%{version}.tar.bz2
Requires: freeswitch = %{version}
Requires: freeswitch
Requires: freeswitch-application-conference
Requires: freeswitch-application-esf
Requires: freeswitch-application-expr
@ -94,14 +94,8 @@ Requires: freeswitch-format-mod-shout
Requires: freeswitch-format-shell-stream
Requires: freeswitch-format-ssml
Requires: freeswitch-sounds-music-8000
Requires: freeswitch-sounds-music-16000
Requires: freeswitch-sounds-music-32000
Requires: freeswitch-sounds-music-48000
Requires: freeswitch-lang-en
Requires: freeswitch-sounds-en-us-callie-8000
Requires: freeswitch-sounds-en-us-callie-16000
Requires: freeswitch-sounds-en-us-callie-32000
Requires: freeswitch-sounds-en-us-callie-48000
BuildRequires: bash
BuildArch: noarch
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
@ -171,6 +165,9 @@ FreeSWITCH rayo server implementation.
#
######################################################################################################################
%changelog
* Tue Jun 10 2014 crienzo@grasshopper.com
- Remove dependency to high resolution music and sounds files
- Remove dependency to specific FreeSWITCH package version
* Mon Jun 03 2013 - crienzo@grasshopper.com
- Added users and internal profile for softphone testing
* Wed May 08 2013 - crienzo@grasshopper.com

3
html5/verto/README Normal file
View File

@ -0,0 +1,3 @@
This needs to be fleshed out more.
It would be nice to develop a web app here that implements a web phone.
Do not base it on the demo because it was just tossed together.

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,65 @@
.nthChildTest > div:nth-child(odd) {
display: none;
}
.jsDataTable > thead > tr > th {
border-width:4px;
padding: 2px;
font-size:10pt;
text-align: left;
}
.jsDataTable > thead > tr > th.notSortable {
padding: 5px;
}
.jsDataTable > tbody > tr > td {
border-bottom: 1px solid #ccc;
padding: 2px;
vertical-align: middle;
height:25px;
}
.jsDataTable {
font-family: verdana;
font-size:10pt;
}
.jsDataTable > tbody > tr:nth-child(odd),
.jsDataTable > tbody > tr.odd {
background-color: #ffffee;
}
.jsDataTable > tbody > tr:nth-child(even),
.jsDataTable > tbody > tr.even {
background-color: #ffffff;
}
.jsDataTable > thead th.sortAsc,
.jsDataTable > thead th.sortDesc {
color:ffffff;
background-color: #7777ff;
background-position: right center;
background-repeat: no-repeat;
}
.jsDataTable > thead th.sortAsc {
background-image: url(/images/table/asc.png);
}
.jsDataTable > thead th.sortDesc {
background-image: url(/images/table/desc.png);
}
.jsDataTable.clickable > tbody > tr,
.clickable > .jsDataTable > tbody > tr {
cursor: pointer;
}
.jsDataTable.clickable > tbody > tr.nonDataRow,
.clickable > .jsDataTable > tbody > tr.nonDataRow {
cursor: auto;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 773 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

281
html5/verto/demo/index.html Normal file
View File

@ -0,0 +1,281 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/jquery.mobile-1.3.2.min.css" />
<link rel="stylesheet" type="text/css" href="css/jsontable.css" />
<link rel="shortcut icon" href="favicon.ico" />
<meta charset="utf-8" />
<title>FreeSWITCH Verto&trade; Demo</title>
<style type="text/css">
.pageheader {
font-size: 22px;
font-weight: normal;
height: 27px;
}
.ctlbtn {
border: 0px;
color: #eeeeee;
background-color: #0000ae;
font-face: arial;
}
.ctlbtn:hover {
color: #ffffae;
cursor: pointer;
}
</style>
</head>
<body>
<div data-role="page" id="page-login" align="center">
<div data-role="header" class="page-header">
FreeSWITCH Verto&trade; Demo
</div>
<br>
<a target="_CC2104" href="https://www.cluecon.com"><img border="0" width="300" src="img/cc_banner2014.gif"></a>
<div data-role="fieldcontain">
<label for="name">Login</label>
<input type="text" size="20" id="login"/>
</div>
<div data-role="fieldcontain">
<label for="name">Password</label>
<input type="password" size="20" id="passwd"/>
</div>
<div data-role="fieldcontain">
<label for="name">CID Name</label>
<input type="text" size="30" id="name"/>
</div>
<div data-role="fieldcontain">
<label for="name">CID Number</label>
<input type="text" size="20" id="cid"/>
</div>
<div data-role="fieldcontain">
<label for="name">Hostname</label>
<input type="text" size="20" id="hostName"/>
</div>
<div data-role="fieldcontain">
<label for="name">Websocket URL</label>
<input type="text" size="20" id="wsURL"/>
</div>
<br><br>
<img src="img/verto_black_web.gif" width="300">
<br><br>
<button data-inline="true" id="loginbtn">Log In</button>
</div>
<div data-role="page" id="page-incall" align="center">
<div data-role="header" id="calltitle" class="pageheader">
Verto&trade; IN CALL
</div>
<br>
<a target="_CC2104" href="https://www.cluecon.com"><img border="0" width="300" src="img/cc_banner2014.gif"></a>
<br><br>
<div id="conf">
<div style="color:black;font-family: verdana" align="center" id="conf_count"></div>
<table width="800" cellspacing="0" cellpadding="0" border="0" align="center" id="conf_list" class="jsDataTable">
</table>
</div>
<div id="display" style="font-weight:bold;font-size:18px"></div>
<br>
<div data-role="fieldcontain" id="xferdiv">
<input data-mini="true" type="text" id="xferto"><br>
<button data-inline="true" id="cancelxferbtn">Cancel Transfer</button>
<button data-inline="true" class="startxferbtn">Complete Transfer</button>
</div>
<div id=keypad>
<button class="dtmf" data-inline="true">1</button>
<button class="dtmf" data-inline="true">2</button>
<button class="dtmf" data-inline="true">3</button>
<br>
<button class="dtmf" data-inline="true">4</button>
<button class="dtmf" data-inline="true">5</button>
<button class="dtmf" data-inline="true">6</button>
<br>
<button class="dtmf" data-inline="true">7</button>
<button class="dtmf" data-inline="true">8</button>
<button class="dtmf" data-inline="true">9</button>
<br>
<button class="dtmf" data-inline="true">*</button>
<button class="dtmf" data-inline="true">0</button>
<button class="dtmf" data-inline="true">#</button>
</div>
<div id="conf_mod"></div>
<div style="color:blue" id="conf_display"></div>
<button data-inline="true" id="hold">HOLD</button>
<button data-inline="true" id="hupbtn">End Call</button>
<button data-inline="true" class="startxferbtn">Transfer</button>
<br><br>
<img src="img/verto_black_web.gif" width="300"><br><br>
<div id="media">
<video width=800 id="webcam" autoplay="autoplay" hidden="true"></video>
</div>
<br><br>
</div>
<div data-role="page" id="page-main" align="center">
<div data-role="header" class="pageheader">
FreeSWITCH Verto&trade; Demo
</div>
<br>
<a target="_CC2104" href="https://www.cluecon.com"><img border="0" width="300" src="img/cc_banner2014.gif"></a>
<div id="offline">
<h2>LOGGING IN</h2>
<img src="images/login.gif"></img>
<div id="errordisplay" style="font-weight:bold;font-size:18px;color:#ae0000"></div>
</div>
<div id="online" align="center">
<div id="text"></div>
<div data-role="fieldcontain">
<input type="text" id="ext"/><br>
<div id="dialpad">
<button class="dialbtn" data-inline="true">1</button>
<button class="dialbtn" data-inline="true">2</button>
<button class="dialbtn" data-inline="true">3</button>
<br>
<button class="dialbtn" data-inline="true">4</button>
<button class="dialbtn" data-inline="true">5</button>
<button class="dialbtn" data-inline="true">6</button>
<br>
<button class="dialbtn" data-inline="true">7</button>
<button class="dialbtn" data-inline="true">8</button>
<button class="dialbtn" data-inline="true">9</button>
<br>
<button class="dialbtn" data-inline="true">*</button>
<button class="dialbtn" data-inline="true">0</button>
<button class="dialbtn" data-inline="true">#</button>
</div>
<button data-inline="true" id="clearbtn">Clear</button>
<button data-inline="true" id="callbtn">Call</button>
<br><br>
<div style="color:blue" id="main_info">&nbsp;</div><br><br>
<img src="img/verto_black_web.gif" width="300"><br><br>
<button data-inline="true"id="logoutbtn">Log Out</button>
</div>
<br>
<label><input id="use_vid" type="checkbox" value="foo" > Use Video</label>
<label><input id="use_stereo" type="checkbox" value="foo" > Stereo Audio</label>
<br>
<!--
<b>TEXT</b><br>To: <input type="text" size="20" id="textto"/> MSG: <input type="text" size="40" id="textmsg"/>
<button id="vtxtbtn">Send</button>
-->
</div>
<table width=500 style="font-size:11pt;font-face:arial">
<tr><td align=center colspan=2><b>FreeSWITCH VERTO&trade; WebRTC Demo Directory<Br><br></td></tr>
<tr><td width=100><b>Dial</b></td><td><b>Desc</b></td></tr>
<tr><td align=left colspan=2><hr></td></tr>
<tr><td>3d1</td><td> 3D sound demo #1</td></tr>
<tr><td>3d2</td><td> 3D sound demo #2</td></tr>
<tr><td>stereo1</td><td> Stereo sound demo #1</td></tr>
<tr><td>stereo2</td><td> Stereo sound demo #2</td></tr>
<tr><td>stereo3</td><td> Stereo sound demo #3</td></tr>
<tr><td>3500</td><td>Local 48k Stereo Conference</td></tr>
<tr><td>&nbsp;</td></tr>
<tr><td>cluecon</td><td> ClueCon Hotline</td></tr>
<tr><td>&lt;number&gt;</td><td>Call a US/Canda Number</td></tr>
<tr><td>vuc</td><td>VoIP Users Conference</td></tr>
<tr><td>888</td><td>FreeSWITCH Community Conference</td></tr>
<tr><td>3300</td><td>Local 48k Conference</td></tr>
<tr><td>5000</td><td>Try the Demo IVR</td></tr>
<tr><td>9664</td><td>Listen to Hold Music</td></tr>
<tr><td>9386</td><td>Funny Prompts</td></tr>
<tr><td>9198</td><td>Tetris (tone generator)</td></tr>
<tr><td colspan=2><Br>
<center>
<br><br><br>
</td></tr>
</td></tr>
</table>
</div><!-- /page -->
<div data-role="page" id="dialog-logout" data-close-btn="none">
<div data-role="header">
<h2>Logged Out</h2>
</div>
<div data-role="content">
<p>You have been logged out or disconnected from the server.</p>
<button onclick="$('#dialog-logout').dialog('close')">OK</button>
</div>
</div>
<div data-role="page" id="dialog-login-error" data-close-btn="none">
<div data-role="header">
<h2>Login Error</h2>
</div>
<div data-role="content">
<p>Error logging in</p>
<button onclick="$('#dialog-login-error').dialog('close')">OK</button>
</div>
</div>
<div data-role="page" id="dialog-hold" data-close-btn="none">
<div data-role="header">
<h2>Call On hold</h2>
</div>
<div data-role="content">
<p>The call is on hold</p>
<button onclick="$('#dialog-hold').dialog('close');cur_call.toggleHold();">Resume Call</button>
</div>
</div>
<div data-role="page" id="dialog-incoming-call" data-close-btn="none">
<div data-role="header">
<h2>Incoming Call</h2>
</div>
<div data-role="content">
<div id="dialog-incoming-call-txt"><p>Incoming Call</p></div>
<button id="ansbtn">Answer</button>
<div id="vansdiv"><button id="vansbtn">Answer Video</button></div>
<button id="declinebtn">Decline</button>
</div>
</div>
<script type="text/javascript" src="js/jquery-2.0.3.min.js"></script>
<script type="text/javascript" src="js/jquery.mobile-1.3.2.min.js"></script>
<script type="text/javascript" src="js/jquery.json-2.4.min.js"></script>
<script type="text/javascript" src="js/jquery.cookie.js"></script>
<script type="text/javascript" src="js/jquery.dataTables.js"></script>
<script type="text/javascript" src="js/verto-min.js"></script>
<script type="text/javascript" src="verto.js"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,90 @@
/*!
* jQuery Cookie Plugin v1.3.1
* https://github.com/carhartl/jquery-cookie
*
* Copyright 2013 Klaus Hartl
* Released under the MIT license
*/
(function ($, document, undefined) {
var pluses = /\+/g;
function raw(s) {
return s;
}
function decoded(s) {
return unRfc2068(decodeURIComponent(s.replace(pluses, ' ')));
}
function unRfc2068(value) {
if (value.indexOf('"') === 0) {
// This is a quoted cookie as according to RFC2068, unescape
value = value.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
}
return value;
}
function fromJSON(value) {
return config.json ? JSON.parse(value) : value;
}
var config = $.cookie = function (key, value, options) {
// write
if (value !== undefined) {
options = $.extend({}, config.defaults, options);
if (value === null) {
options.expires = -1;
}
if (typeof options.expires === 'number') {
var days = options.expires, t = options.expires = new Date();
t.setDate(t.getDate() + days);
}
value = config.json ? JSON.stringify(value) : String(value);
return (document.cookie = [
encodeURIComponent(key), '=', config.raw ? value : encodeURIComponent(value),
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
options.path ? '; path=' + options.path : '',
options.domain ? '; domain=' + options.domain : '',
options.secure ? '; secure' : ''
].join(''));
}
// read
var decode = config.raw ? raw : decoded;
var cookies = document.cookie.split('; ');
var result = key ? null : {};
for (var i = 0, l = cookies.length; i < l; i++) {
var parts = cookies[i].split('=');
var name = decode(parts.shift());
var cookie = decode(parts.join('='));
if (key && key === name) {
result = fromJSON(cookie);
break;
}
if (!key) {
result[name] = fromJSON(cookie);
}
}
return result;
};
config.defaults = {};
$.removeCookie = function (key, options) {
if ($.cookie(key) !== null) {
$.cookie(key, null, options);
return true;
}
return false;
};
})(jQuery, document);

12099
html5/verto/demo/js/jquery.dataTables.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,23 @@
/*! jQuery JSON plugin 2.4.0 | code.google.com/p/jquery-json */
(function($){'use strict';var escape=/["\\\x00-\x1f\x7f-\x9f]/g,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},hasOwn=Object.prototype.hasOwnProperty;$.toJSON=typeof JSON==='object'&&JSON.stringify?JSON.stringify:function(o){if(o===null){return'null';}
var pairs,k,name,val,type=$.type(o);if(type==='undefined'){return undefined;}
if(type==='number'||type==='boolean'){return String(o);}
if(type==='string'){return $.quoteString(o);}
if(typeof o.toJSON==='function'){return $.toJSON(o.toJSON());}
if(type==='date'){var month=o.getUTCMonth()+1,day=o.getUTCDate(),year=o.getUTCFullYear(),hours=o.getUTCHours(),minutes=o.getUTCMinutes(),seconds=o.getUTCSeconds(),milli=o.getUTCMilliseconds();if(month<10){month='0'+month;}
if(day<10){day='0'+day;}
if(hours<10){hours='0'+hours;}
if(minutes<10){minutes='0'+minutes;}
if(seconds<10){seconds='0'+seconds;}
if(milli<100){milli='0'+milli;}
if(milli<10){milli='0'+milli;}
return'"'+year+'-'+month+'-'+day+'T'+
hours+':'+minutes+':'+seconds+'.'+milli+'Z"';}
pairs=[];if($.isArray(o)){for(k=0;k<o.length;k++){pairs.push($.toJSON(o[k])||'null');}
return'['+pairs.join(',')+']';}
if(typeof o==='object'){for(k in o){if(hasOwn.call(o,k)){type=typeof k;if(type==='number'){name='"'+k+'"';}else if(type==='string'){name=$.quoteString(k);}else{continue;}
type=typeof o[k];if(type!=='function'&&type!=='undefined'){val=$.toJSON(o[k]);pairs.push(name+':'+val);}}}
return'{'+pairs.join(',')+'}';}};$.evalJSON=typeof JSON==='object'&&JSON.parse?JSON.parse:function(str){return eval('('+str+')');};$.secureEvalJSON=typeof JSON==='object'&&JSON.parse?JSON.parse:function(str){var filtered=str.replace(/\\["\\\/bfnrtu]/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,'');if(/^[\],:{}\s]*$/.test(filtered)){return eval('('+str+')');}
throw new SyntaxError('Error parsing JSON, source is not valid.');};$.quoteString=function(str){if(str.match(escape)){return'"'+str.replace(escape,function(a){var c=meta[a];if(typeof c==='string'){return c;}
c=a.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+(c%16).toString(16);})+'"';}
return'"'+str+'"';};}(jQuery));

File diff suppressed because one or more lines are too long

215
html5/verto/demo/js/verto-min.js vendored Normal file
View File

@ -0,0 +1,215 @@
(function($){function findLine(sdpLines,prefix,substr){return findLineInRange(sdpLines,0,-1,prefix,substr);}
function findLineInRange(sdpLines,startLine,endLine,prefix,substr){var realEndLine=(endLine!=-1)?endLine:sdpLines.length;for(var i=startLine;i<realEndLine;++i){if(sdpLines[i].indexOf(prefix)===0){if(!substr||sdpLines[i].toLowerCase().indexOf(substr.toLowerCase())!==-1){return i;}}}
return null;}
function getCodecPayloadType(sdpLine){var pattern=new RegExp('a=rtpmap:(\\d+) \\w+\\/\\d+');var result=sdpLine.match(pattern);return(result&&result.length==2)?result[1]:null;}
function setDefaultCodec(mLine,payload){var elements=mLine.split(' ');var newLine=[];var index=0;for(var i=0;i<elements.length;i++){if(index===3)
newLine[index++]=payload;if(elements[i]!==payload)newLine[index++]=elements[i];}
return newLine.join(' ');}
$.FSRTC=function(options){this.options=$.extend({useVideo:null,useStereo:false,userData:null,videoParams:{},callbacks:{onICEComplete:function(){},onICE:function(){},onOfferSDP:function(){}}},options);this.mediaData={SDP:null,profile:{},candidateList:[]};this.constraints={optional:[{'DtlsSrtpKeyAgreement':'true'}],mandatory:{OfferToReceiveAudio:true,OfferToReceiveVideo:this.options.useVideo?true:false,}};if(self.options.useVideo){self.options.useVideo.style.display='none';}
setCompat();checkCompat();};$.FSRTC.prototype.useVideo=function(obj){var self=this;if(obj){self.options.useVideo=obj;self.constraints.mandatory.OfferToReceiveVideo=true;}else{self.options.useVideo=null;self.constraints.mandatory.OfferToReceiveVideo=false;}
if(self.options.useVideo){self.options.useVideo.style.display='none';}};$.FSRTC.prototype.useStereo=function(on){var self=this;self.options.useStereo=on;};$.FSRTC.prototype.stereoHack=function(sdp){var self=this;if(!self.options.useStereo){return sdp;}
var sdpLines=sdp.split('\r\n');var opusIndex=findLine(sdpLines,'a=rtpmap','opus/48000'),opusPayload;if(opusIndex){opusPayload=getCodecPayloadType(sdpLines[opusIndex]);}
var fmtpLineIndex=findLine(sdpLines,'a=fmtp:'+opusPayload.toString());if(fmtpLineIndex===null)return sdp;sdpLines[fmtpLineIndex]=sdpLines[fmtpLineIndex].concat('; stereo=1');sdp=sdpLines.join('\r\n');return sdp;};function setCompat(){$.FSRTC.moz=!!navigator.mozGetUserMedia;if(!navigator.getUserMedia){navigator.getUserMedia=navigator.mozGetUserMedia||navigator.webkitGetUserMedia||navigator.msGetUserMedia;}}
function checkCompat(){if(!navigator.getUserMedia){alert('This application cannot function in this browser.');return false;}
return true;}
function onStreamError(self){console.log('There has been a problem retrieving the streams - did you allow access?');}
function onStreamSuccess(self){console.log("Stream Success");}
function onICE(self,candidate){self.mediaData.candidate=candidate;self.mediaData.candidateList.push(self.mediaData.candidate);doCallback(self,"onICE");}
function doCallback(self,func,arg){if(func in self.options.callbacks){self.options.callbacks[func](self,arg);}}
function onICEComplete(self,candidate){console.log("ICE Complete");doCallback(self,"onICEComplete");}
function onChannelError(self,e){console.error("Channel Error",e);doCallback(self,"onError",e);}
function onICESDP(self,sdp){self.mediaData.SDP=self.stereoHack(sdp.sdp);console.log("ICE SDP");doCallback(self,"onICESDP");}
function onAnswerSDP(self,sdp){self.answer.SDP=self.stereoHack(sdp.sdp);console.log("ICE ANSWER SDP");doCallback(self,"onAnswerSDP",self.answer.SDP);}
function onMessage(self,msg){console.log("Message");doCallback(self,"onICESDP",msg);}
function onRemoteStream(self,stream){if(self.options.useVideo){self.options.useVideo.style.display='block';}
var element=self.options.useAudio;console.log("REMOTE STREAM",stream,element);if(typeof element.srcObject!=='undefined'){element.srcObject=stream;}else if(typeof element.mozSrcObject!=='undefined'){element.mozSrcObject=stream;}else if(typeof element.src!=='undefined'){element.src=URL.createObjectURL(stream);}else{console.error('Error attaching stream to element.');}
self.options.useAudio.play();self.remoteStream=stream;}
function onOfferSDP(self,sdp){self.mediaData.SDP=self.stereoHack(sdp.sdp);console.log("Offer SDP");doCallback(self,"onOfferSDP");}
$.FSRTC.prototype.answer=function(sdp,onSuccess,onError){this.peer.addAnswerSDP({type:"answer",sdp:sdp},onSuccess,onError);};$.FSRTC.prototype.stop=function(){var self=this;if(self.options.useVideo){self.options.useVideo.style.display='none';}
if(self.localStream){self.localStream.stop();self.localStream=null;}
if(self.peer){console.log("stopping peer");self.peer.stop();}};$.FSRTC.prototype.createAnswer=function(sdp){var self=this;self.type="answer";self.remoteSDP=sdp;console.debug("inbound sdp: ",sdp);function onSuccess(stream){self.localStream=stream;self.peer=RTCPeerConnection({type:self.type,attachStream:self.localStream,onICE:function(candidate){return onICE(self,candidate);},onICEComplete:function(){return onICEComplete(self);},onRemoteStream:function(stream){return onRemoteStream(self,stream);},onICESDP:function(sdp){return onICESDP(self,sdp);},onChannelError:function(e){return onChannelError(self,e);},constraints:self.constraints,offerSDP:{type:"offer",sdp:self.remoteSDP}});onStreamSuccess(self);}
function onError(){onStreamError(self);}
getUserMedia({constraints:{audio:true,video:this.options.useVideo?{mandatory:this.options.videoParams,optional:[]}:null},video:this.options.useVideo?true:false,onsuccess:onSuccess,onerror:onError});};$.FSRTC.prototype.call=function(profile){checkCompat();var self=this;self.type="offer";function onSuccess(stream){self.localStream=stream;self.peer=RTCPeerConnection({type:self.type,attachStream:self.localStream,onICE:function(candidate){return onICE(self,candidate);},onICEComplete:function(){return onICEComplete(self);},onRemoteStream:function(stream){return onRemoteStream(self,stream);},onOfferSDP:function(sdp){return onOfferSDP(self,sdp);},onICESDP:function(sdp){return onICESDP(self,sdp);},onChannelError:function(e){return onChannelError(self,e);},constraints:self.constraints});onStreamSuccess(self);}
function onError(){onStreamError(self);}
getUserMedia({constraints:{audio:true,video:this.options.useVideo?{mandatory:this.options.videoParams,optional:[]}:null},video:this.options.useVideo?true:false,onsuccess:onSuccess,onerror:onError});};window.moz=!!navigator.mozGetUserMedia;function RTCPeerConnection(options){var w=window,PeerConnection=w.mozRTCPeerConnection||w.webkitRTCPeerConnection,SessionDescription=w.mozRTCSessionDescription||w.RTCSessionDescription,IceCandidate=w.mozRTCIceCandidate||w.RTCIceCandidate;var STUN={url:!moz?'stun:stun.l.google.com:19302':'stun:23.21.150.121'};var TURN={url:'turn:homeo@turn.bistri.com:80',credential:'homeo'};var iceServers={iceServers:options.iceServers||[STUN]};if(!moz&&!options.iceServers){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];}
var optional={optional:[]};if(!moz){optional.optional=[{DtlsSrtpKeyAgreement:true},{RtpDataChannels:options.onChannelMessage?true:false}];}
var peer=new PeerConnection(iceServers,optional);openOffererChannel();var x=0;peer.onicecandidate=function(event){if(event.candidate){options.onICE(event.candidate);}else{if(options.onICEComplete){options.onICEComplete();}
if(options.type=="offer"){if(!moz&&!x&&options.onICESDP){options.onICESDP(peer.localDescription);}}else{if(!x&&options.onICESDP){options.onICESDP(peer.localDescription);}}}};if(options.attachStream)peer.addStream(options.attachStream);if(options.attachStreams&&options.attachStream.length){var streams=options.attachStreams;for(var i=0;i<streams.length;i++){peer.addStream(streams[i]);}}
peer.onaddstream=function(event){var remoteMediaStream=event.stream;remoteMediaStream.onended=function(){if(options.onRemoteStreamEnded)options.onRemoteStreamEnded(remoteMediaStream);};if(options.onRemoteStream)options.onRemoteStream(remoteMediaStream);};var constraints=options.constraints||{optional:[],mandatory:{OfferToReceiveAudio:true,OfferToReceiveVideo:true}};function createOffer(){if(!options.onOfferSDP)return;peer.createOffer(function(sessionDescription){sessionDescription.sdp=serializeSdp(sessionDescription.sdp);peer.setLocalDescription(sessionDescription);options.onOfferSDP(sessionDescription);if(moz&&options.onICESDP){options.onICESDP(sessionDescription);}},onSdpError,constraints);}
function createAnswer(){if(options.type!="answer")return;peer.setRemoteDescription(new SessionDescription(options.offerSDP),onSdpSuccess,onSdpError);peer.createAnswer(function(sessionDescription){sessionDescription.sdp=serializeSdp(sessionDescription.sdp);peer.setLocalDescription(sessionDescription);if(options.onAnswerSDP){options.onAnswerSDP(sessionDescription);}},onSdpError,constraints);}
if((options.onChannelMessage&&!moz)||!options.onChannelMessage){createOffer();createAnswer();}
function setBandwidth(sdp){sdp=sdp.replace(/b=AS([^\r\n]+\r\n)/g,'');sdp=sdp.replace(/a=mid:data\r\n/g,'a=mid:data\r\nb=AS:1638400\r\n');return sdp;}
function getInteropSDP(sdp){var chars='ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''),extractedChars='';function getChars(){extractedChars+=chars[parseInt(Math.random()*40)]||'';if(extractedChars.length<40)getChars();return extractedChars;}
if(options.onAnswerSDP)sdp=sdp.replace(/(a=crypto:0 AES_CM_128_HMAC_SHA1_32)(.*?)(\r\n)/g,'');var inline=getChars()+'\r\n'+(extractedChars='');sdp=sdp.indexOf('a=crypto')==-1?sdp.replace(/c=IN/g,'a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:'+inline+'c=IN'):sdp;return sdp;}
function serializeSdp(sdp){return sdp;}
var channel;function openOffererChannel(){if(!options.onChannelMessage||(moz&&!options.onOfferSDP))return;_openOffererChannel();if(!moz)return;navigator.mozGetUserMedia({audio:true,fake:true},function(stream){peer.addStream(stream);createOffer();},useless);}
function _openOffererChannel(){channel=peer.createDataChannel(options.channel||'RTCDataChannel',moz?{}:{reliable:false});if(moz)channel.binaryType='blob';setChannelEvents();}
function setChannelEvents(){channel.onmessage=function(event){if(options.onChannelMessage)options.onChannelMessage(event);};channel.onopen=function(){if(options.onChannelOpened)options.onChannelOpened(channel);};channel.onclose=function(event){if(options.onChannelClosed)options.onChannelClosed(event);console.warn('WebRTC DataChannel closed',event);};channel.onerror=function(event){if(options.onChannelError)options.onChannelError(event);console.error('WebRTC DataChannel error',event);};}
if(options.onAnswerSDP&&moz&&options.onChannelMessage)openAnswererChannel();function openAnswererChannel(){peer.ondatachannel=function(event){channel=event.channel;channel.binaryType='blob';setChannelEvents();};if(!moz)return;navigator.mozGetUserMedia({audio:true,fake:true},function(stream){peer.addStream(stream);createAnswer();},useless);}
function useless(){log('Error in fake:true');}
function onSdpSuccess(){}
function onSdpError(e){if(options.onChannelError){options.onChannelError(e);}
console.error('sdp error:',e);}
return{addAnswerSDP:function(sdp,cbSuccess,cbError){peer.setRemoteDescription(new SessionDescription(sdp),cbSuccess?cbSuccess:onSdpSuccess,cbError?cbError:onSdpError);},addICE:function(candidate){peer.addIceCandidate(new IceCandidate({sdpMLineIndex:candidate.sdpMLineIndex,candidate:candidate.candidate}));},peer:peer,channel:channel,sendData:function(message){if(channel){channel.send(message);}},stop:function(){peer.close();if(options.attachStream){options.attachStream.stop();}}};}
var video_constraints={mandatory:{},optional:[]};function getUserMedia(options){var n=navigator,media;n.getMedia=n.webkitGetUserMedia||n.mozGetUserMedia;n.getMedia(options.constraints||{audio:true,video:video_constraints},streaming,options.onerror||function(e){console.error(e);});function streaming(stream){var video=options.video;if(video){video[moz?'mozSrcObject':'src']=moz?stream:window.webkitURL.createObjectURL(stream);}
if(options.onsuccess){options.onsuccess(stream);}
media=stream;}
return media;}})(jQuery);(function($){$.JsonRpcClient=function(options){var self=this;this.options=$.extend({ajaxUrl:null,socketUrl:null,onmessage:null,login:null,passwd:null,sessid:null,getSocket:function(onmessage_cb){return self._getSocket(onmessage_cb);}},options);this.wsOnMessage=function(event){self._wsOnMessage(event);};};$.JsonRpcClient.prototype._ws_socket=null;$.JsonRpcClient.prototype._ws_callbacks={};$.JsonRpcClient.prototype._current_id=1;$.JsonRpcClient.prototype.call=function(method,params,success_cb,error_cb){if(!params){params={};}
if(this.options.sessid){params.sessid=this.options.sessid;}
var request={jsonrpc:'2.0',method:method,params:params,id:this._current_id++};if(!success_cb){success_cb=function(e){console.log("Success: ",e);};}
if(!error_cb){error_cb=function(e){console.log("Error: ",e);};}
var socket=this.options.getSocket(this.wsOnMessage);if(socket!==null){this._wsCall(socket,request,success_cb,error_cb);return;}
if(this.options.ajaxUrl===null){throw"$.JsonRpcClient.call used with no websocket and no http endpoint.";}
$.ajax({type:'POST',url:this.options.ajaxUrl,data:$.toJSON(request),dataType:'json',cache:false,success:function(data){if('error'in data)error_cb(data.error,this);success_cb(data.result,this);},error:function(jqXHR,textStatus,errorThrown){try{var response=$.parseJSON(jqXHR.responseText);if('console'in window)console.log(response);error_cb(response.error,this);}
catch(err){error_cb({error:jqXHR.responseText},this);}}});};$.JsonRpcClient.prototype.notify=function(method,params){if(this.options.sessid){params.sessid=this.options.sessid;}
var request={jsonrpc:'2.0',method:method,params:params};var socket=this.options.getSocket(this.wsOnMessage);if(socket!==null){this._wsCall(socket,request);return;}
if(this.options.ajaxUrl===null){throw"$.JsonRpcClient.notify used with no websocket and no http endpoint.";}
$.ajax({type:'POST',url:this.options.ajaxUrl,data:$.toJSON(request),dataType:'json',cache:false});};$.JsonRpcClient.prototype.batch=function(callback,all_done_cb,error_cb){var batch=new $.JsonRpcClient._batchObject(this,all_done_cb,error_cb);callback(batch);batch._execute();};$.JsonRpcClient.prototype.socketReady=function(){if(this._ws_socket===null||this._ws_socket.readyState>1){return false;}
return true;}
$.JsonRpcClient.prototype.closeSocket=function(){if(self.socketReady()){this._ws_socket.onclose=function(w){console.log("Closing Socket")}
this._ws_socket.close();}}
$.JsonRpcClient.prototype.loginData=function(params){self.options.login=params.login;self.options.passwd=params.passwd;}
$.JsonRpcClient.prototype.connectSocket=function(onmessage_cb){var self=this;if(!self.socketReady()){self.authing=false;this._ws_socket=new WebSocket(this.options.socketUrl);if(this._ws_socket){this._ws_socket.onmessage=onmessage_cb;this._ws_socket.onclose=function(w){if(!self.ws_sleep){self.ws_sleep=2;}
self.ws_cnt=0;if(self.options.onWSClose){self.options.onWSClose(self);}
console.error("Websocket Lost sleep: "+self.ws_sleep+"sec");setTimeout(function(){console.log("Attempting Reconnection....");self.connectSocket(onmessage_cb);},self.ws_sleep*1000);if(++self.ws_cnt>=150){self.ws_sleep=30;}}
this._ws_socket.onopen=function(){this.ws_sleep=2;this.ws_cnt=0;if(self.options.onWSConnect){self.options.onWSConnect(self);}
var req;while(req=$.JsonRpcClient.q.pop()){self._ws_socket.send(req);}}}}
return this._ws_socket?true:false;}
$.JsonRpcClient.prototype._getSocket=function(onmessage_cb){if(this.options.socketUrl===null||!("WebSocket"in window))return null;this.connectSocket(onmessage_cb);return this._ws_socket;};$.JsonRpcClient.q=[];$.JsonRpcClient.prototype._wsCall=function(socket,request,success_cb,error_cb){var request_json=$.toJSON(request);if(socket.readyState<1){self=this;$.JsonRpcClient.q.push(request_json);}
else{socket.send(request_json);}
if('id'in request&&typeof success_cb!=='undefined'){this._ws_callbacks[request.id]={request:request_json,request_obj:request,success_cb:success_cb,error_cb:error_cb};}};$.JsonRpcClient.prototype._wsOnMessage=function(event){var response;try{response=$.parseJSON(event.data);if(typeof response==='object'&&'jsonrpc'in response&&response.jsonrpc==='2.0'){if('result'in response&&this._ws_callbacks[response.id]){var success_cb=this._ws_callbacks[response.id].success_cb;delete this._ws_callbacks[response.id];success_cb(response.result,this);return;}
else if('error'in response&&this._ws_callbacks[response.id]){var error_cb=this._ws_callbacks[response.id].error_cb;var orig_req=this._ws_callbacks[response.id].request;if(!self.authing&&response.error.code==-32000&&self.options.login&&self.options.passwd){self.authing=true;this.call("login",{login:self.options.login,passwd:self.options.passwd},this._ws_callbacks[response.id].request_obj.method=="login"?function(e){self.authing=false;console.log("logged in");delete self._ws_callbacks[response.id];if(self.options.onWSLogin){self.options.onWSLogin(true,self);}}:function(e){self.authing=false;console.log("logged in, resending request id: "+response.id);var socket=self.options.getSocket(self.wsOnMessage);if(socket!==null){socket.send(orig_req);}
if(self.options.onWSLogin){self.options.onWSLogin(true,self);}},function(e){console.log("error logging in, request id:",response.id);delete self._ws_callbacks[response.id];error_cb(response.error,this);if(self.options.onWSLogin){self.options.onWSLogin(false,self);}});return;}
delete this._ws_callbacks[response.id];error_cb(response.error,this);return;}}}
catch(err){console.log("ERROR: "+err);return;}
if(typeof this.options.onmessage==='function'){event.eventData=response;if(!event.eventData){event.eventData={};}
var reply=this.options.onmessage(event);if(reply&&typeof reply==="object"&&event.eventData.id){var msg={jsonrpc:"2.0",id:event.eventData.id,result:reply};var socket=self.options.getSocket(self.wsOnMessage);if(socket!==null){socket.send($.toJSON(msg));}}}};$.JsonRpcClient._batchObject=function(jsonrpcclient,all_done_cb,error_cb){this._requests=[];this.jsonrpcclient=jsonrpcclient;this.all_done_cb=all_done_cb;this.error_cb=typeof error_cb==='function'?error_cb:function(){};};$.JsonRpcClient._batchObject.prototype.call=function(method,params,success_cb,error_cb){if(!params){params={};}
if(this.options.sessid){params.sessid=this.options.sessid;}
if(!success_cb){success_cb=function(e){console.log("Success: ",e);};}
if(!error_cb){error_cb=function(e){console.log("Error: ",e);};}
this._requests.push({request:{jsonrpc:'2.0',method:method,params:params,id:this.jsonrpcclient._current_id++},success_cb:success_cb,error_cb:error_cb});};$.JsonRpcClient._batchObject.prototype.notify=function(method,params){if(this.options.sessid){params.sessid=this.options.sessid;}
this._requests.push({request:{jsonrpc:'2.0',method:method,params:params}});};$.JsonRpcClient._batchObject.prototype._execute=function(){var self=this;if(this._requests.length===0)return;var batch_request=[];var handlers={};var socket=self.jsonrpcclient.options.getSocket(self.jsonrpcclient.wsOnMessage);if(socket!==null){for(var i=0;i<this._requests.length;i++){var call=this._requests[i];var success_cb=('success_cb'in call)?call.success_cb:undefined;var error_cb=('error_cb'in call)?call.error_cb:undefined;self.jsonrpcclient._wsCall(socket,call.request,success_cb,error_cb);}
if(typeof all_done_cb==='function')all_done_cb(result);return;}
for(var i=0;i<this._requests.length;i++){var call=this._requests[i];batch_request.push(call.request);if('id'in call.request){handlers[call.request.id]={success_cb:call.success_cb,error_cb:call.error_cb};}}
var success_cb=function(data){self._batchCb(data,handlers,self.all_done_cb);};if(self.jsonrpcclient.options.ajaxUrl===null){throw"$.JsonRpcClient.batch used with no websocket and no http endpoint.";}
$.ajax({url:self.jsonrpcclient.options.ajaxUrl,data:$.toJSON(batch_request),dataType:'json',cache:false,type:'POST',error:function(jqXHR,textStatus,errorThrown){self.error_cb(jqXHR,textStatus,errorThrown);},success:success_cb});};$.JsonRpcClient._batchObject.prototype._batchCb=function(result,handlers,all_done_cb){for(var i=0;i<result.length;i++){var response=result[i];if('error'in response){if(response.id===null||!(response.id in handlers)){if('console'in window)console.log(response);}
else handlers[response.id].error_cb(response.error,this);}
else{if(!(response.id in handlers)&&'console'in window)console.log(response);else handlers[response.id].success_cb(response.result,this);}}
if(typeof all_done_cb==='function')all_done_cb(result);};})(jQuery);(function($){var generateGUID=(typeof(window.crypto)!=='undefined'&&typeof(window.crypto.getRandomValues)!=='undefined')?function(){var buf=new Uint16Array(8);window.crypto.getRandomValues(buf);var S4=function(num){var ret=num.toString(16);while(ret.length<4){ret="0"+ret;}
return ret;};return(S4(buf[0])+S4(buf[1])+"-"+S4(buf[2])+"-"+S4(buf[3])+"-"+S4(buf[4])+"-"+S4(buf[5])+S4(buf[6])+S4(buf[7]));}:function(){return'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,function(c){var r=Math.random()*16|0,v=c=='x'?r:(r&0x3|0x8);return v.toString(16);});};$.verto=function(options,callbacks){var verto=this;$.verto.saved.push(verto);verto.options=$.extend({login:null,passwd:null,socketUrl:null,tag:null,videoParams:{},ringSleep:6000},options);verto.sessid=$.cookie('verto_session_uuid')||generateGUID();$.cookie('verto_session_uuid',verto.sessid,{expires:1});verto.dialogs={};verto.callbacks=callbacks||{};verto.eventSUBS={};verto.rpcClient=new $.JsonRpcClient({login:verto.options.login,passwd:verto.options.passwd,socketUrl:verto.options.socketUrl,sessid:verto.sessid,onmessage:function(e){return verto.handleMessage(e.eventData);},onWSConnect:function(o){o.call('login',{});},onWSLogin:function(success){if(verto.callbacks.onWSLogin){verto.callbacks.onWSLogin(verto,success);}},onWSClose:function(success){if(verto.callbacks.onWSClose){verto.callbacks.onWSClose(verto,success);}
verto.purge();}});if(verto.options.ringFile&&verto.options.tag){verto.ringer=$("#"+verto.options.tag);}
verto.rpcClient.call('login',{});};$.verto.prototype.loginData=function(params){verto.options.login=params.login;verto.options.passwd=params.passwd;verto.rpcClient.loginData(params);};$.verto.prototype.logout=function(msg){var verto=this;verto.rpcClient.closeSocket();verto.purge();};$.verto.prototype.login=function(msg){var verto=this;verto.logout();verto.rpcClient.call('login',{});};$.verto.prototype.message=function(msg){var verto=this;var err=0;if(!msg.to){console.error("Missing To");err++;}
if(!msg.body){console.error("Missing Body");err++;}
if(err){return false;}
verto.sendMethod("verto.info",{msg:msg});return true;};$.verto.prototype.processReply=function(method,success,e){var verto=this;var i;console.log("Response: "+method,success,e);switch(method){case"verto.subscribe":for(i in e.unauthorizedChannels){drop_bad(verto,e.unauthorizedChannels[i]);}
for(i in e.subscribedChannels){mark_ready(verto,e.subscribedChannels[i]);}
break;case"verto.unsubscribe":break;}};$.verto.prototype.sendMethod=function(method,params){var verto=this;verto.rpcClient.call(method,params,function(e){verto.processReply(method,true,e);},function(e){verto.processReply(method,false,e);});};function do_sub(verto,channel,obj){}
function drop_bad(verto,channel){console.error("drop unauthorized channel: "+channel);delete verto.eventSUBS[channel];}
function mark_ready(verto,channel){for(var j in verto.eventSUBS[channel]){verto.eventSUBS[channel][j].ready=true;console.log("subscribed to channel: "+channel);if(verto.eventSUBS[channel][j].readyHandler){verto.eventSUBS[channel][j].readyHandler(verto,channel);}}}
var SERNO=1;function do_subscribe(verto,channel,subChannels,sparams){var params=sparams||{};var local=params.local;var obj={eventChannel:channel,userData:params.userData,handler:params.handler,ready:false,readyHandler:params.readyHandler,serno:SERNO++};var isnew=false;if(!verto.eventSUBS[channel]){verto.eventSUBS[channel]=[];subChannels.push(channel);isnew=true;}
verto.eventSUBS[channel].push(obj);if(local){obj.ready=true;obj.local=true;}
if(!isnew&&verto.eventSUBS[channel][0].ready){obj.ready=true;if(obj.readyHandler){obj.readyHandler(verto,channel);}}
return{serno:obj.serno,eventChannel:channel};}
$.verto.prototype.subscribe=function(channel,sparams){var verto=this;var r=[];var subChannels=[];var params=sparams||{};if(typeof(channel)==="string"){r.push(do_subscribe(verto,channel,subChannels,params));}else{for(var i in channel){r.push(do_subscribe(verto,channel,subChannels,params));}}
if(subChannels.length){verto.sendMethod("verto.subscribe",{eventChannel:subChannels.length==1?subChannels[0]:subChannels,subParams:params.subParams});}
return r;};$.verto.prototype.unsubscribe=function(handle){var verto=this;var i;if(!handle){for(i in verto.eventSUBS){if(verto.eventSUBS[i]){verto.unsubscribe(verto.eventSUBS[i]);}}}else{var unsubChannels={};var sendChannels=[];var channel;if(typeof(handle)=="string"){delete verto.eventSUBS[handle];unsubChannels[handle]++;}else{for(i in handle){if(typeof(handle[i])=="string"){channel=handle[i];delete verto.eventSUBS[channel];unsubChannels[channel]++;}else{var repl=[];channel=handle[i].eventChannel;for(var j in verto.eventSUBS[channel]){if(verto.eventSUBS[channel][j].serno==handle[i].serno){}else{repl.push(verto.eventSUBS[channel][j]);}}
verto.eventSUBS[channel]=repl;if(verto.eventSUBS[channel].length===0){delete verto.eventSUBS[channel];unsubChannels[channel]++;}}}}
for(var u in unsubChannels){console.log("Sending Unsubscribe for: ",u);sendChannels.push(u);}
if(sendChannels.length){verto.sendMethod("verto.unsubscribe",{eventChannel:sendChannels.length==1?sendChannels[0]:sendChannels});}}};$.verto.prototype.broadcast=function(channel,params){var verto=this;var msg={eventChannel:channel,data:{}};for(var i in params){msg.data[i]=params[i];}
verto.sendMethod("verto.broadcast",msg);};$.verto.prototype.purge=function(callID){var verto=this;var x=0;var i;for(i in verto.dialogs){if(!x){console.log("purging dialogs");}
x++;verto.dialogs[i].setState($.verto.enum.state.purge);}
for(i in verto.eventSUBS){if(verto.eventSUBS[i]){console.log("purging subscription: "+i);delete verto.eventSUBS[i];}}};$.verto.prototype.hangup=function(callID){var verto=this;if(callID){var dialog=verto.dialogs[callID];if(dialog){dialog.hangup();}}else{for(var i in verto.dialogs){verto.dialogs[i].hangup();}}};$.verto.prototype.newCall=function(args,callbacks){var verto=this;if(!verto.rpcClient.socketReady()){console.error("Not Connected...");return;}
var dialog=new $.verto.dialog($.verto.enum.direction.outbound,this,args);dialog.invite();if(callbacks){dialog.callbacks=callbacks;}
return dialog;};$.verto.prototype.handleMessage=function(data){var verto=this;if(data.params.callID){var dialog=verto.dialogs[data.params.callID];if(dialog){switch(data.method){case'verto.bye':dialog.hangup(data.params);break;case'verto.answer':dialog.handleAnswer(data.params);break;case'verto.media':dialog.handleMedia(data.params);break;case'verto.display':dialog.handleDisplay(data.params);break;case'verto.info':dialog.handleInfo(data.params);break;default:console.debug("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED",data.method);break;}}else{switch(data.method){case'verto.attach':data.params.attach=true;if(data.params.sdp&&data.params.sdp.indexOf("m=video")>0){data.params.useVideo=true;}
if(data.params.sdp&&data.params.sdp.indexOf("stereo=1")>0){data.params.useStereo=true;}
dialog=new $.verto.dialog($.verto.enum.direction.inbound,verto,data.params);break;case'verto.invite':if(data.params.sdp&&data.params.sdp.indexOf("m=video")>0){data.params.wantVideo=true;}
if(data.params.sdp&&data.params.sdp.indexOf("stereo=1")>0){data.params.useStereo=true;}
dialog=new $.verto.dialog($.verto.enum.direction.inbound,verto,data.params);break;default:console.debug("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED");break;}}
return{method:data.method};}else{switch(data.method){case'verto.event':var list=null;var key=null;if(data.params){key=data.params.eventChannel;}
if(key){list=verto.eventSUBS[key];if(!list){list=verto.eventSUBS[key.split(".")[0]];}}
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){if(!key){key="UNDEFINED";}
console.error("UNSUBBED or invalid EVENT "+key+" IGNORED");}else{for(var i in list){var sub=list[i];if(!sub||!sub.ready){console.error("invalid EVENT for "+key+" IGNORED");}else if(sub.handler){sub.handler(verto,data.params,sub.userData);}else if(verto.callbacks.onEvent){verto.callbacks.onEvent(verto,data.params,sub.userData);}else{console.log("EVENT:",data.params);}}}
break;case"verto.info":if(verto.callbacks.onMessage){verto.callbacks.onMessage(verto,null,$.verto.enum.message.info,data.params.msg);}
console.error(data);console.debug("MESSAGE from: "+data.params.msg.from,data.params.msg.body);break;default:console.error("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED",data.method);break;}}};var del_array=function(array,name){var r=[];var len=array.length;for(var i=0;i<len;i++){if(array[i]!=name){r.push(array[i]);}}
return r;};var hashArray=function(){var vha=this;var hash={};var array=[];vha.reorder=function(a){array=a;var h=hash;hash={};var len=array.length;for(var i=0;i<len;i++){var key=array[i];if(h[key]){hash[key]=h[key];delete h[key];}}
h=undefined;};vha.clear=function(){hash=undefined;array=undefined;hash={};array=[];};vha.add=function(name,val,insertAt){var redraw=false;if(!hash[name]){if(insertAt===undefined||insertAt<0||insertAt>=array.length){array.push(name);}else{var x=0;var n=[];var len=array.length;for(var i=0;i<len;i++){if(x++==insertAt){n.push(name);}
n.push(array[i]);}
array=undefined;array=n;n=undefined;redraw=true;}}
hash[name]=val;return redraw;};vha.del=function(name){var r=false;if(hash[name]){array=del_array(array,name);delete hash[name];r=true;}else{console.error("can't del nonexistant key "+name);}
return r;};vha.get=function(name){return hash[name];};vha.order=function(){return array;};vha.hash=function(){return hash;};vha.indexOf=function(name){var len=array.length;for(var i=0;i<len;i++){if(array[i]==name){return i;}}};vha.arrayLen=function(){return array.length;};vha.asArray=function(){var r=[];var len=array.length;for(var i=0;i<len;i++){var key=array[i];r.push(hash[key]);}
return r;};vha.each=function(cb){var len=array.length;for(var i=0;i<len;i++){cb(array[i],hash[array[i]]);}};vha.dump=function(html){var str="";vha.each(function(name,val){str+="name: "+name+" val: "+JSON.stringify(val)+(html?"<br>":"\n");});return str;};};$.verto.liveArray=function(verto,context,name,config){var la=this;var lastSerno=0;var binding=null;var user_obj=config.userObj;var local=false;hashArray.call(la);la._add=la.add;la._del=la.del;la._reorder=la.reorder;la._clear=la.clear;la.context=context;la.name=name;la.user_obj=user_obj;la.verto=verto;la.broadcast=function(channel,obj){verto.broadcast(channel,obj);};la.errs=0;la.clear=function(){la._clear();lastSerno=0;if(la.onChange){la.onChange(la,{action:"clear"});}};la.checkSerno=function(serno){if(serno<0){return true;}
if(lastSerno>0&&serno!=(lastSerno+1)){if(la.onErr){la.onErr(la,{lastSerno:lastSerno,serno:serno});}
la.errs++;console.debug(la.errs);if(la.errs<3){la.bootstrap(la.user_obj);}
return false;}else{lastSerno=serno;return true;}};la.reorder=function(serno,a){if(la.checkSerno(serno)){la._reorder(a);if(la.onChange){la.onChange(la,{serno:serno,action:"reorder"});}}};la.init=function(serno,val,key,index){if(key===null||key===undefined){key=serno;}
if(la.checkSerno(serno)){if(la.onChange){la.onChange(la,{serno:serno,action:"init",index:index,key:key,data:val});}}};la.bootObj=function(serno,val){if(la.checkSerno(serno)){for(var i in val){la._add(val[i][0],val[i][1]);}
if(la.onChange){la.onChange(la,{serno:serno,action:"bootObj",data:val,redraw:true});}}};la.add=function(serno,val,key,index){if(key===null||key===undefined){key=serno;}
if(la.checkSerno(serno)){var redraw=la._add(key,val,index);if(la.onChange){la.onChange(la,{serno:serno,action:"add",index:index,key:key,data:val,redraw:redraw});}}};la.modify=function(serno,val,key,index){if(key===null||key===undefined){key=serno;}
if(la.checkSerno(serno)){la._add(key,val,index);if(la.onChange){la.onChange(la,{serno:serno,action:"modify",key:key,data:val,index:index});}}};la.del=function(serno,key,index){if(key===null||key===undefined){key=serno;}
if(la.checkSerno(serno)){if(index===null||index<0||index===undefined){index=la.indexOf(key);}
var ok=la._del(key);if(ok&&la.onChange){la.onChange(la,{serno:serno,action:"del",key:key,index:index});}}};var eventHandler=function(v,e,la){var packet=e.data;console.error("READ:",packet);if(packet.name!=la.name){return;}
switch(packet.action){case"init":la.init(packet.wireSerno,packet.data,packet.hashKey,packet.arrIndex);break;case"bootObj":la.bootObj(packet.wireSerno,packet.data);break;case"add":la.add(packet.wireSerno,packet.data,packet.hashKey,packet.arrIndex);break;case"modify":if(!(packet.arrIndex||packet.hashKey)){console.error("Invalid Packet",packet);}else{la.modify(packet.wireSerno,packet.data,packet.hashKey,packet.arrIndex);}
break;case"del":if(!(packet.arrIndex||packet.hashKey)){console.error("Invalid Packet",packet);}else{la.del(packet.wireSerno,packet.hashKey,packet.arrIndex);}
break;case"clear":la.clear();break;case"reorder":la.reorder(packet.wireSerno,packet.order);break;default:if(la.checkSerno(packet.wireSerno)){if(la.onChange){la.onChange(la,{serno:packet.wireSerno,action:packet.action,data:packet.data});}}
break;}};if(la.context){binding=la.verto.subscribe(la.context,{handler:eventHandler,userData:la,subParams:config.subParams});}
la.destroy=function(){la._clear();la.verto.unsubscribe(binding);};la.sendCommand=function(cmd,obj){var self=la;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.changepage=function(obj){var self=la;self.clear();self.broadcast(self.context,{liveArray:{command:"changepage",context:la.context,name:la.name,obj:obj}});};la.heartbeat=function(obj){var self=la;var callback=function(){self.heartbeat.call(self,obj);};self.broadcast(self.context,{liveArray:{command:"heartbeat",context:self.context,name:self.name,obj:obj}});self.hb_pid=setTimeout(callback,30000);};la.bootstrap(la.user_obj);};$.verto.liveTable=function(verto,context,name,jq,config){var dt;var la=new $.verto.liveArray(verto,context,name,{subParams:config.subParams});var lt=this;lt.liveArray=la;lt.dataTable=dt;lt.verto=verto;lt.destroy=function(){if(dt){dt.fnDestroy();}
if(la){la.destroy();}
dt=null;la=null;};la.onErr=function(obj,args){console.error("Error: ",obj,args);};la.onChange=function(obj,args){var index=0;var iserr=0;if(!dt){if(!config.aoColumns){if(args.action!="init"){return;}
config.aoColumns=[];for(var i in args.data){config.aoColumns.push({"sTitle":args.data[i]});}}
dt=jq.dataTable(config);}
if(dt&&(args.action=="del"||args.action=="modify")){index=args.index;if(index===undefined&&args.key){index=la.indexOf(args.key);}
if(index===undefined){console.error("INVALID PACKET Missing INDEX\n",args);return;}}
if(config.onChange){config.onChange(obj,args);}
try{switch(args.action){case"bootObj":if(!args.data){console.error("missing data");return;}
dt.fnClearTable();dt.fnAddData(obj.asArray());dt.fnAdjustColumnSizing();break;case"add":if(!args.data){console.error("missing data");return;}
if(args.redraw>-1){dt.fnClearTable();dt.fnAddData(obj.asArray());}else{dt.fnAddData(args.data);}
dt.fnAdjustColumnSizing();break;case"modify":if(!args.data){return;}
console.debug(args,index);dt.fnUpdate(args.data,index);dt.fnAdjustColumnSizing();break;case"del":dt.fnDeleteRow(index);dt.fnAdjustColumnSizing();break;case"clear":dt.fnClearTable();break;case"reorder":dt.fnClearTable();dt.fnAddData(obj.asArray());break;case"hide":jq.hide();break;case"show":jq.show();break;}}catch(err){console.error("ERROR: "+err);iserr++;}
if(iserr){obj.errs++;if(obj.errs<3){obj.bootstrap(obj.user_obj);}}else{obj.errs=0;}};la.onChange(la,{action:"init"});};var CONFMAN_SERNO=1;$.verto.confMan=function(verto,params){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);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;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>";jq.html(html);$("#"+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");});$("#"+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"]);});}
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 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>"+"</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();});$("#"+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;$(".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.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("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);}},"aaData":[],"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,"bInfo":false,"bFilter":false,"bLengthChange":false,"bPaginate":false,"iDisplayLength":1000,"oLanguage":{"sEmptyTable":"The Conference is Empty....."},"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}});}
$.verto.confMan.prototype.destroy=function(){var confMan=this;if(confMan.lt){confMan.lt.destroy();}
if(confMan.params.laData.modChannel){confMan.verto.unsubscribe(confMan.params.laData.modChannel);}
if(confMan.params.mainModID){$(confMan.params.mainModID).html("");}}
$.verto.dialog=function(direction,verto,params){var dialog=this;dialog.params=$.extend({useVideo:verto.options.useVideo,useStereo:verto.options.useStereo,tag:verto.options.tag},params);dialog.verto=verto;dialog.direction=direction;dialog.lastState=null;dialog.state=dialog.lastState=$.verto.enum.state.new;dialog.callbacks=verto.callbacks;dialog.answered=false;dialog.attach=params.attach||false;if(dialog.params.callID){dialog.callID=dialog.params.callID;}else{dialog.callID=dialog.params.callID=generateGUID();}
if(dialog.params.tag){dialog.audioStream=document.getElementById(dialog.params.tag);if(dialog.params.useVideo){dialog.videoStream=dialog.audioStream;}}
dialog.verto.dialogs[dialog.callID]=dialog;var RTCcallbacks={};if(dialog.direction==$.verto.enum.direction.inbound){dialog.params.remote_caller_id_name=dialog.params.caller_id_name;dialog.params.remote_caller_id_number=dialog.params.caller_id_number;if(!dialog.params.remote_caller_id_name){dialog.params.remote_caller_id_name="Nobody";}
if(!dialog.params.remote_caller_id_number){dialog.params.remote_caller_id_number="UNKNOWN";}
RTCcallbacks.onMessage=function(rtc,msg){console.debug(msg);};RTCcallbacks.onAnswerSDP=function(rtc,sdp){console.error("answer sdp",sdp);};}else{dialog.params.remote_caller_id_name="Outbound Call";dialog.params.remote_caller_id_number=dialog.params.destination_number;}
RTCcallbacks.onICESDP=function(rtc){if(rtc.type=="offer"){console.log("offer",rtc.mediaData.SDP);dialog.setState($.verto.enum.state.requesting);dialog.sendMethod("verto.invite",{sdp:rtc.mediaData.SDP});}else{dialog.setState($.verto.enum.state.answering);dialog.sendMethod(dialog.attach?"verto.attach":"verto.answer",{sdp:dialog.rtc.mediaData.SDP});}};RTCcallbacks.onICE=function(rtc){if(rtc.type=="offer"){console.log("offer",rtc.mediaData.candidate);return;}};RTCcallbacks.onError=function(e){console.error("ERROR:",e);dialog.hangup();};dialog.rtc=new $.FSRTC({callbacks:RTCcallbacks,useVideo:dialog.videoStream,useAudio:dialog.audioStream,useStereo:dialog.params.useStereo,videoParams:verto.options.videoParams,});dialog.rtc.verto=dialog.verto;if(dialog.direction==$.verto.enum.direction.inbound){if(dialog.attach){dialog.answer();}else{dialog.ring();}}};$.verto.dialog.prototype.invite=function(){var dialog=this;dialog.rtc.call();};$.verto.dialog.prototype.sendMethod=function(method,obj){var dialog=this;obj.dialogParams={};for(var i in dialog.params){if(i=="sdp"&&method!="verto.invite"&&method!="verto.attach"){continue;}
obj.dialogParams[i]=dialog.params[i];}
dialog.verto.rpcClient.call(method,obj,function(e){dialog.processReply(method,true,e);},function(e){dialog.processReply(method,false,e);});};function checkStateChange(oldS,newS){if(newS==$.verto.enum.state.purge||$.verto.enum.states[oldS.name][newS.name]){return true;}
return false;}
$.verto.dialog.prototype.setState=function(state){var dialog=this;if(dialog.state==$.verto.enum.state.ringing){dialog.stopRinging();}
if(dialog.state==state||!checkStateChange(dialog.state,state)){console.error("Dialog "+dialog.callID+": INVALID state change from "+dialog.state.name+" to "+state.name);dialog.hangup();return false;}
console.error("Dialog "+dialog.callID+": state change from "+dialog.state.name+" to "+state.name);dialog.lastState=dialog.state;dialog.state=state;if(!dialog.causeCode){dialog.causeCode=16;}
if(!dialog.cause){dialog.cause="NORMAL CLEARING";}
if(dialog.callbacks.onDialogState){dialog.callbacks.onDialogState(this);}
switch(dialog.state){case $.verto.enum.state.purge:dialog.setState($.verto.enum.state.destroy);break;case $.verto.enum.state.hangup:if(dialog.lastState.val>$.verto.enum.state.requesting.val&&dialog.lastState.val<$.verto.enum.state.hangup.val){dialog.sendMethod("verto.bye",{});}
dialog.setState($.verto.enum.state.destroy);break;case $.verto.enum.state.destroy:delete verto.dialogs[dialog.callID];dialog.rtc.stop();break;}
return true;};$.verto.dialog.prototype.processReply=function(method,success,e){var dialog=this;console.log("Response: "+method+" State:"+dialog.state.name,success,e);switch(method){case"verto.answer":case"verto.attach":if(success){dialog.setState($.verto.enum.state.active);}else{dialog.hangup();}
break;case"verto.invite":if(success){dialog.setState($.verto.enum.state.trying);}else{dialog.setState($.verto.enum.state.destroy);}
break;case"verto.bye":dialog.hangup();break;case"verto.modify":if(e.holdState){if(e.holdState=="held"){if(dialog.state!=$.verto.enum.state.held){dialog.setState($.verto.enum.state.held);}}else if(e.holdState=="active"){if(dialog.state!=$.verto.enum.state.active){dialog.setState($.verto.enum.state.active);}}}
if(success){}
break;default:break;}};$.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(dialog.state.val>$.verto.enum.state.new.val&&dialog.state.val<$.verto.enum.state.hangup.val){dialog.setState($.verto.enum.state.hangup);}else if(dialog.state.val<$.verto.enum.state.destroy){dialog.setState($.verto.enum.state.destroy);}};$.verto.dialog.prototype.stopRinging=function(){var dialog=this;if(dialog.verto.ringer){dialog.verto.ringer.stop();}};$.verto.dialog.prototype.indicateRing=function(){var dialog=this;if(dialog.verto.ringer){dialog.verto.ringer.attr("src",dialog.verto.options.ringFile)[0].play();setTimeout(function(){dialog.stopRinging();if(dialog.state==$.verto.enum.state.ringing){dialog.indicateRing();}},dialog.verto.options.ringSleep);}};$.verto.dialog.prototype.ring=function(){var dialog=this;dialog.setState($.verto.enum.state.ringing);dialog.indicateRing();};$.verto.dialog.prototype.useVideo=function(on){var dialog=this;dialog.params.useVideo=on;if(on){dialog.videoStream=dialog.audioStream;}else{dialog.videoStream=null;}
dialog.rtc.useVideo(dialog.videoStream);};$.verto.dialog.prototype.useStereo=function(on){var dialog=this;dialog.params.useStereo=on;dialog.rtc.useStereo(on);};$.verto.dialog.prototype.dtmf=function(digits){var dialog=this;if(digits){dialog.sendMethod("verto.info",{dtmf:digits});}};$.verto.dialog.prototype.transfer=function(dest,params){var dialog=this;if(dest){cur_call.sendMethod("verto.modify",{action:"transfer",destination:dest,params:params});}};$.verto.dialog.prototype.hold=function(params){var dialog=this;cur_call.sendMethod("verto.modify",{action:"hold",params:params});};$.verto.dialog.prototype.unhold=function(params){var dialog=this;cur_call.sendMethod("verto.modify",{action:"unhold",params:params});};$.verto.dialog.prototype.toggleHold=function(params){var dialog=this;cur_call.sendMethod("verto.modify",{action:"toggleHold",params:params});};$.verto.dialog.prototype.message=function(msg){var dialog=this;var err=0;if(!msg.to){console.error("Missing To");err++;}
if(!msg.body){console.error("Missing Body");err++;}
if(err){return false;}
dialog.sendMethod("verto.info",{msg:msg});return true;};$.verto.dialog.prototype.answer=function(params){var dialog=this;if(!dialog.answered){if(params){if(params.useVideo){dialog.useVideo(true);}}
dialog.rtc.createAnswer(dialog.params.sdp);dialog.answered=true;}};$.verto.dialog.prototype.handleAnswer=function(params){var dialog=this;if(dialog.state.val>=$.verto.enum.state.active.val){return;}
if(dialog.state.val>=$.verto.enum.state.early.val){dialog.setState($.verto.enum.state.active);}else{dialog.rtc.answer(params.sdp,function(){dialog.setState($.verto.enum.state.active);},function(e){console.error(e);dialog.hangup();});console.log("ANSWER SDP",params.sdp);}};$.verto.dialog.prototype.cidString=function(enc){var dialog=this;var party=dialog.params.remote_caller_id_name+(enc?" &lt;":" <")+dialog.params.remote_caller_id_number+(enc?"&gt;":">");return party;};$.verto.dialog.prototype.sendMessage=function(msg,params){var dialog=this;if(dialog.callbacks.onMessage){dialog.callbacks.onMessage(dialog.verto,dialog,msg,params);}};$.verto.dialog.prototype.handleInfo=function(params){var dialog=this;dialog.sendMessage($.verto.enum.message.info,params.msg);};$.verto.dialog.prototype.handleDisplay=function(params){var dialog=this;if(params.display_name){dialog.params.remote_caller_id_name=params.display_name;}
if(params.display_number){dialog.params.remote_caller_id_number=params.display_number;}
dialog.sendMessage($.verto.enum.message.display,{});};$.verto.dialog.prototype.handleMedia=function(params){var dialog=this;if(dialog.state.val>=$.verto.enum.state.early.val){return;}
dialog.rtc.answer(params.sdp,function(){dialog.setState($.verto.enum.state.early);},function(e){console.error(e);dialog.hangup();});console.log("EARLY SDP",params.sdp);};$.verto.ENUM=function(s){var i=0,o={};s.split(" ").map(function(x){o[x]={name:x,val:i++};});return Object.freeze(o);};$.verto.enum={};$.verto.enum.states=Object.freeze({new:{requesting:1,ringing:1,destroy:1,answering:1},requesting:{trying:1,hangup:1},trying:{active:1,early:1,hangup:1},ringing:{answering:1,hangup:1},answering:{active:1,hangup:1},active:{hangup:1,held:1},held:{hangup:1,active:1},early:{hangup:1,active:1},hangup:{destroy:1},destroy:{},purge:{destroy:1}});$.verto.enum.state=$.verto.ENUM("new requesting trying ringing answering early active held hangup destroy purge");$.verto.enum.direction=$.verto.ENUM("inbound outbound");$.verto.enum.message=$.verto.ENUM("display info pvtEvent");$.verto.enum=Object.freeze($.verto.enum);$.verto.saved=[];$(window).bind('beforeunload',function(){for(var i in $.verto.saved){var verto=$.verto.saved[i];if(verto){verto.logout();verto.purge();}}
return $.verto.warnOnUnload;});})(jQuery);

Binary file not shown.

Binary file not shown.

412
html5/verto/demo/verto.js Normal file
View File

@ -0,0 +1,412 @@
'use strict';
var cur_call = null;
var confMan = null;
var $display = $("#display");
var verto;
var ringing = false;
function display(msg) {
$("#calltitle").html(msg);
}
function clearConfMan() {
if (confMan) {
confMan.destroy();
confMan = null;
}
$("#conf").hide();
}
function goto_dialog(where) {
$.mobile.changePage("#dialog-" + where, {
role: "dialog"
});
}
function goto_page(where) {
$.mobile.changePage("#page-" + where);
}
var first_login = false;
var online_visible = false;
function online(on) {
if (on) {
$("#online").show();
$("#offline").hide();
first_login = true;
} else {
if (first_login && online_visible) {
goto_dialog("logout");
}
$("#online").hide();
$("#offline").show();
}
online_visible = on;
}
function check_vid() {
var use_vid = $("#use_vid").is(':checked');
return use_vid;
}
var callbacks = {
onMessage: function(verto, dialog, msg, data) {
switch (msg) {
case $.verto.enum.message.pvtEvent:
console.error("pvtEvent", data.pvtData.action);
if (data.pvtData) {
switch (data.pvtData.action) {
case "conference-liveArray-part":
clearConfMan();
break;
case "conference-liveArray-join":
clearConfMan();
confMan = new $.verto.confMan(verto, {
tableID: "#conf_list",
statusID: "#conf_count",
mainModID: "#conf_mod",
displayID: "#conf_display",
dialog: dialog,
hasVid: check_vid(),
laData: data.pvtData
});
$("#conf").show();
break;
}
}
break;
case $.verto.enum.message.info:
$("#text").html("Message from: <b>" + data.from + "</b>:<br>" + "<pre>" + data.body + "</pre>");
break;
case $.verto.enum.message.display:
var party = dialog.params.remote_caller_id_name + "<" + dialog.params.remote_caller_id_number + ">";
display("Talking to: " + dialog.cidString());
break;
default:
break;
}
},
onDialogState: function(d) {
cur_call = d;
if (d.state == $.verto.enum.state.ringing) {
ringing = true;
} else {
ringing = false;
}
switch (d.state) {
case $.verto.enum.state.ringing:
display("Call From: " + d.cidString());
$("#ansbtn").click(function() {
cur_call.answer({
useStereo: $("#use_stereo").is(':checked')
});
$('#dialog-incoming-call').dialog('close');
});
$("#declinebtn").click(function() {
cur_call.hangup();
$('#dialog-incoming-call').dialog('close');
});
goto_dialog("incoming-call");
$("#dialog-incoming-call-txt").text("Incoming call from: " + d.cidString());
if (d.params.wantVideo) {
$("#vansbtn").click(function() {
$("#use_vid").prop("checked", true);
cur_call.answer({
useVideo: true,
useStereo: $("#use_stereo").is(':checked')
});
});
// the buttons in this jquery mobile wont hide .. gotta wrap them in a div as a workaround
$("#vansdiv").show();
} else {
$("#vansdiv").hide();
}
break;
case $.verto.enum.state.early:
case $.verto.enum.state.active:
display("Talking to: " + d.cidString());
goto_page("incall");
break;
case $.verto.enum.state.hangup:
$("#main_info").html("Call ended with cause: " + d.cause);
case $.verto.enum.state.destroy:
$("#hangup_cause").html("");
clearConfMan();
goto_page("main");
cur_call = null;
break;
case $.verto.enum.state.held:
break;
default:
display("");
break;
}
},
onWSLogin: function(v, success) {
display("");
cur_call = null;
ringing = false;
if (success) {
online(true);
verto.subscribe("presence", {
handler: function(v, e) {
console.error("PRESENCE:", e);
}
});
if (!window.location.hash) {
goto_page("main");
}
} else {
goto_page("login");
goto_dialog("login-error");
}
},
onWSClose: function(v, success) {
if ($('#online').is(':visible')) {
display("");
online(false);
}
var today = new Date();
$("#errordisplay").html("Connection Error.<br>Last Attempt: " + today);
goto_page("main");
},
onEvent: function(v, e) {
console.debug("w00t", e);
},
};
$("#hold").click(function(e) {
cur_call.toggleHold();
goto_dialog("hold");
});
$("#cancelxferbtn").click(function(e) {
$("#xferto").val("");
$("#xferdiv").hide();
});
$(".startxferbtn").click(function(e) {
if ($('#xferdiv').is(':visible')) {
var xfer = $("#xferto").val();
if (xfer) {
cur_call.transfer(xfer);
}
$("#xferto").val("");
$("#xferdiv").hide();
} else {
$("#xferdiv").show();
}
});
$("#clearbtn").click(function(e) {
$("#ext").val("");
});
$(".dialbtn").click(function(e) {
$("#ext").val($("#ext").val() + e.currentTarget.textContent);
});
$(".dtmf").click(function(e) {
if ($('#xferdiv').is(':visible')) {
$("#xferto").val($("#xferto").val() + e.currentTarget.textContent);
} else {
cur_call.dtmf(e.currentTarget.textContent);
}
});
$("#hupbtn").click(function() {
verto.hangup();
cur_call = null;
});
$("#webcam").click(function() {
check_vid();
});
$("#callbtn").click(function() {
$('#ext').trigger('change');
if (cur_call) {
return;
}
$("#main_info").html("Trying");
cur_call = verto.newCall({
destination_number: $("#ext").val(),
caller_id_name: $("#name").val(),
caller_id_number: $("#cid").val(),
useVideo: check_vid(),
useStereo: $("#use_stereo").is(':checked')
});
});
function pop(id, cname, dft) {
var tmp = $.cookie(cname) || dft;
$.cookie(cname, tmp, {
expires: 365
});
$(id).val(tmp).change(function() {
$.cookie(cname, $(id).val(), {
expires: 365
});
});
}
function init() {
cur_call = null;
pop("#ext", "verto_demo_ext", "3500");
pop("#name", "verto_demo_name", "FreeSWITCH User");
pop("#cid", "verto_demo_cid", "1008");
pop("#textto", "verto_demo_textto", "1000");
pop("#login", "verto_demo_login", "1008");
pop("#passwd", "verto_demo_passwd", "1234");
pop("#hostName", "verto_demo_hostname", window.location.hostname);
pop("#wsURL", "verto_demo_wsurl", "wss://" + window.location.hostname + ":8082");
var tmp = $.cookie("verto_demo_vid_checked") || "false";
$.cookie("verto_demo_vid_checked", tmp, {
expires: 365
});
$("#use_vid").prop("checked", tmp === "true").change(function(e) {
tmp = $("#use_vid").is(':checked');
$.cookie("verto_demo_vid_checked", tmp ? "true" : "false", {
expires: 365
});
});
tmp = $.cookie("verto_demo_stereo_checked") || "false";
$.cookie("verto_demo_stereo_checked", tmp, {
expires: 365
});
$("#use_stereo").prop("checked", tmp === "true").change(function(e) {
tmp = $("#use_stereo").is(':checked');
$.cookie("verto_demo_stereo_checked", tmp ? "true" : "false", {
expires: 365
});
});
verto = new $.verto({
login: $("#login").val() + "@" + $("#hostName").val(),
passwd: $("#passwd").val(),
socketUrl: $("#wsURL").val(),
tag: "webcam",
ringFile: "sounds/bell_ring2.wav",
videoParams: {
"minWidth": "1280",
"minHeight": "720"
}
},callbacks);
$("#login").change(function(e) {
$("#cid").val(e.currentTarget.value);
$.cookie("verto_demo_cid", e.currentTarget.value, {
expires: 365
});
});
$("#vtxtbtn").click(function() {
verto.message({
to: $("#textto").val(),
body: $("#textmsg").val()
});
$("#textmsg").val("");
});
$("#logoutbtn").click(function() {
verto.logout();
goto_page("login");
online(false);
});
$("#loginbtn").click(function() {
online(false);
verto.loginData({
login: $("#login").val() + "@" + $("#hostName").val(),
passwd: $("#passwd").val()
});
verto.login();
goto_page("main");
});
$("#xferdiv").hide();
$("#webcam").hide();
online(false);
}
$(document).ready(function() {
init();
$("#page-incall").on("pagebeforechange", function(event) {});
});
$(document).bind("pagebeforechange", function(e, data) {
if (typeof(data.toPage) !== "string") {
return;
}
switch (window.location.hash) {
case "#page-incall":
console.error(e, data);
setTimeout(function() {
if (!cur_call) {
goto_page("main");
}
},
10000);
break;
case "#page-main":
console.error(e, data);
setTimeout(function() {
if (cur_call && !ringing) {
goto_page("incall");
}
},
2000);
break;
case "#page-login":
setTimeout(function() {
if (online_visible) {
goto_page("main");
}
},
1000);
break;
}
});

15
html5/verto/js/Makefile Normal file
View File

@ -0,0 +1,15 @@
JSFILES=src/jquery.FSRTC.js src/jquery.jsonrpcclient.js src/jquery.verto.js
all: jsmin verto-min.js
jsmin: jsmin.c
$(CC) $< -o $@
verto-min.js: jsmin $(JSFILES)
cat $(JSFILES) | ./jsmin > $@
clean:
rm -f verto-min.js jsmin *~
install-demo: all
cp verto-min.js ../demo/js

10
html5/verto/js/README Normal file
View File

@ -0,0 +1,10 @@
This file needs to say more.
Documentation for the api needs to be developed with jsdoc-toolkit http://pulkitgoyal.in/documenting-jquery-plugins-jsdoc-toolkit/
Dependancies for DEMO
jquery-2.0.3.min.js
jquery-2.0.3.min.map
jquery.cookie.js
jquery.dataTables.js
jquery.json-2.4.min.js
jquery.mobile-1.3.2.min.js

306
html5/verto/js/jsmin.c Normal file
View File

@ -0,0 +1,306 @@
/* jsmin.c
2013-03-29
Copyright (c) 2002 Douglas Crockford (www.crockford.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <stdlib.h>
#include <stdio.h>
static int theA;
static int theB;
static int theLookahead = EOF;
static int theX = EOF;
static int theY = EOF;
static void
error(char* s)
{
fputs("JSMIN Error: ", stderr);
fputs(s, stderr);
fputc('\n', stderr);
exit(1);
}
/* isAlphanum -- return true if the character is a letter, digit, underscore,
dollar sign, or non-ASCII character.
*/
static int
isAlphanum(int c)
{
return ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'Z') || c == '_' || c == '$' || c == '\\' ||
c > 126);
}
/* get -- return the next character from stdin. Watch out for lookahead. If
the character is a control character, translate it to a space or
linefeed.
*/
static int
get()
{
int c = theLookahead;
theLookahead = EOF;
if (c == EOF) {
c = getc(stdin);
}
if (c >= ' ' || c == '\n' || c == EOF) {
return c;
}
if (c == '\r') {
return '\n';
}
return ' ';
}
/* peek -- get the next character without getting it.
*/
static int
peek()
{
theLookahead = get();
return theLookahead;
}
/* next -- get the next character, excluding comments. peek() is used to see
if a '/' is followed by a '/' or '*'.
*/
static int
next()
{
int c = get();
if (c == '/') {
switch (peek()) {
case '/':
for (;;) {
c = get();
if (c <= '\n') {
break;
}
}
break;
case '*':
get();
while (c != ' ') {
switch (get()) {
case '*':
if (peek() == '/') {
get();
c = ' ';
}
break;
case EOF:
error("Unterminated comment.");
}
}
break;
}
}
theY = theX;
theX = c;
return c;
}
/* action -- do something! What you do is determined by the argument:
1 Output A. Copy B to A. Get the next B.
2 Copy B to A. Get the next B. (Delete A).
3 Get the next B. (Delete B).
action treats a string as a single character. Wow!
action recognizes a regular expression if it is preceded by ( or , or =.
*/
static void
action(int d)
{
switch (d) {
case 1:
putc(theA, stdout);
if (
(theY == '\n' || theY == ' ') &&
(theA == '+' || theA == '-' || theA == '*' || theA == '/') &&
(theB == '+' || theB == '-' || theB == '*' || theB == '/')
) {
putc(theY, stdout);
}
case 2:
theA = theB;
if (theA == '\'' || theA == '"' || theA == '`') {
for (;;) {
putc(theA, stdout);
theA = get();
if (theA == theB) {
break;
}
if (theA == '\\') {
putc(theA, stdout);
theA = get();
}
if (theA == EOF) {
error("Unterminated string literal.");
}
}
}
case 3:
theB = next();
if (theB == '/' && (
theA == '(' || theA == ',' || theA == '=' || theA == ':' ||
theA == '[' || theA == '!' || theA == '&' || theA == '|' ||
theA == '?' || theA == '+' || theA == '-' || theA == '~' ||
theA == '*' || theA == '/' || theA == '{' || theA == '\n'
)) {
putc(theA, stdout);
if (theA == '/' || theA == '*') {
putc(' ', stdout);
}
putc(theB, stdout);
for (;;) {
theA = get();
if (theA == '[') {
for (;;) {
putc(theA, stdout);
theA = get();
if (theA == ']') {
break;
}
if (theA == '\\') {
putc(theA, stdout);
theA = get();
}
if (theA == EOF) {
error("Unterminated set in Regular Expression literal.");
}
}
} else if (theA == '/') {
switch (peek()) {
case '/':
case '*':
error("Unterminated set in Regular Expression literal.");
}
break;
} else if (theA =='\\') {
putc(theA, stdout);
theA = get();
}
if (theA == EOF) {
error("Unterminated Regular Expression literal.");
}
putc(theA, stdout);
}
theB = next();
}
}
}
/* jsmin -- Copy the input to the output, deleting the characters which are
insignificant to JavaScript. Comments will be removed. Tabs will be
replaced with spaces. Carriage returns will be replaced with linefeeds.
Most spaces and linefeeds will be removed.
*/
static void
jsmin()
{
if (peek() == 0xEF) {
get();
get();
get();
}
theA = '\n';
action(3);
while (theA != EOF) {
switch (theA) {
case ' ':
action(isAlphanum(theB) ? 1 : 2);
break;
case '\n':
switch (theB) {
case '{':
case '[':
case '(':
case '+':
case '-':
case '!':
case '~':
action(1);
break;
case ' ':
action(3);
break;
default:
action(isAlphanum(theB) ? 1 : 2);
}
break;
default:
switch (theB) {
case ' ':
action(isAlphanum(theA) ? 1 : 3);
break;
case '\n':
switch (theA) {
case '}':
case ']':
case ')':
case '+':
case '-':
case '"':
case '\'':
case '`':
action(1);
break;
default:
action(isAlphanum(theA) ? 1 : 3);
}
break;
default:
action(1);
break;
}
}
}
}
/* main -- Output any command line arguments as comments
and then minify the input.
*/
extern int
main(int argc, char* argv[])
{
int i;
for (i = 1; i < argc; i += 1) {
fprintf(stdout, "// %s\n", argv[i]);
}
jsmin();
return 0;
}

View File

@ -0,0 +1,756 @@
/*
* Verto HTML5/Javascript Telephony Signaling and Control Protocol Stack for FreeSWITCH
* Copyright (C) 2005-2014, 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 Verto HTML5/Javascript Telephony Signaling and Control Protocol Stack for FreeSWITCH
*
* 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>
*
* jquery.FSRTC.js - WebRTC Glue code
*
*/
(function($) {
// Find the line in sdpLines that starts with |prefix|, and, if specified,
// contains |substr| (case-insensitive search).
function findLine(sdpLines, prefix, substr) {
return findLineInRange(sdpLines, 0, -1, prefix, substr);
}
// Find the line in sdpLines[startLine...endLine - 1] that starts with |prefix|
// and, if specified, contains |substr| (case-insensitive search).
function findLineInRange(sdpLines, startLine, endLine, prefix, substr) {
var realEndLine = (endLine != -1) ? endLine : sdpLines.length;
for (var i = startLine; i < realEndLine; ++i) {
if (sdpLines[i].indexOf(prefix) === 0) {
if (!substr || sdpLines[i].toLowerCase().indexOf(substr.toLowerCase()) !== -1) {
return i;
}
}
}
return null;
}
// Gets the codec payload type from an a=rtpmap:X line.
function getCodecPayloadType(sdpLine) {
var pattern = new RegExp('a=rtpmap:(\\d+) \\w+\\/\\d+');
var result = sdpLine.match(pattern);
return (result && result.length == 2) ? result[1] : null;
}
// Returns a new m= line with the specified codec as the first one.
function setDefaultCodec(mLine, payload) {
var elements = mLine.split(' ');
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 (elements[i] !== payload) newLine[index++] = elements[i];
}
return newLine.join(' ');
}
$.FSRTC = function(options) {
this.options = $.extend({
useVideo: null,
useStereo: false,
userData: null,
videoParams: {},
callbacks: {
onICEComplete: function() {},
onICE: function() {},
onOfferSDP: function() {}
}
},
options);
this.mediaData = {
SDP: null,
profile: {},
candidateList: []
};
this.constraints = {
optional: [{
'DtlsSrtpKeyAgreement': 'true'
}],
mandatory: {
OfferToReceiveAudio: true,
OfferToReceiveVideo: this.options.useVideo ? true : false,
}
};
if (self.options.useVideo) {
self.options.useVideo.style.display = 'none';
}
setCompat();
checkCompat();
};
$.FSRTC.prototype.useVideo = function(obj) {
var self = this;
if (obj) {
self.options.useVideo = obj;
self.constraints.mandatory.OfferToReceiveVideo = true;
} else {
self.options.useVideo = null;
self.constraints.mandatory.OfferToReceiveVideo = false;
}
if (self.options.useVideo) {
self.options.useVideo.style.display = 'none';
}
};
$.FSRTC.prototype.useStereo = function(on) {
var self = this;
self.options.useStereo = on;
};
// Sets Opus in stereo if stereo is enabled, by adding the stereo=1 fmtp param.
$.FSRTC.prototype.stereoHack = function(sdp) {
var self = this;
if (!self.options.useStereo) {
return sdp;
}
var sdpLines = sdp.split('\r\n');
// Find opus payload.
var opusIndex = findLine(sdpLines, 'a=rtpmap', 'opus/48000'),
opusPayload;
if (opusIndex) {
opusPayload = getCodecPayloadType(sdpLines[opusIndex]);
}
// Find the payload in fmtp line.
var fmtpLineIndex = findLine(sdpLines, 'a=fmtp:' + opusPayload.toString());
if (fmtpLineIndex === null) return sdp;
// Append stereo=1 to fmtp line.
sdpLines[fmtpLineIndex] = sdpLines[fmtpLineIndex].concat('; stereo=1');
sdp = sdpLines.join('\r\n');
return sdp;
};
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;
}
}
function checkCompat() {
if (!navigator.getUserMedia) {
alert('This application cannot function in this browser.');
return false;
}
return true;
}
function onStreamError(self) {
console.log('There has been a problem retrieving the streams - did you allow access?');
}
function onStreamSuccess(self) {
console.log("Stream Success");
}
function onICE(self, candidate) {
self.mediaData.candidate = candidate;
self.mediaData.candidateList.push(self.mediaData.candidate);
doCallback(self, "onICE");
}
function doCallback(self, func, arg) {
if (func in self.options.callbacks) {
self.options.callbacks[func](self, arg);
}
}
function onICEComplete(self, candidate) {
console.log("ICE Complete");
doCallback(self, "onICEComplete");
}
function onChannelError(self, e) {
console.error("Channel Error", e);
doCallback(self, "onError", e);
}
function onICESDP(self, sdp) {
self.mediaData.SDP = self.stereoHack(sdp.sdp);
console.log("ICE SDP");
doCallback(self, "onICESDP");
}
function onAnswerSDP(self, sdp) {
self.answer.SDP = self.stereoHack(sdp.sdp);
console.log("ICE ANSWER SDP");
doCallback(self, "onAnswerSDP", self.answer.SDP);
}
function onMessage(self, msg) {
console.log("Message");
doCallback(self, "onICESDP", msg);
}
function onRemoteStream(self, stream) {
if (self.options.useVideo) {
self.options.useVideo.style.display = 'block';
}
var element = self.options.useAudio;
console.log("REMOTE STREAM", stream, element);
if (typeof element.srcObject !== 'undefined') {
element.srcObject = stream;
} else if (typeof element.mozSrcObject !== 'undefined') {
element.mozSrcObject = stream;
} else if (typeof element.src !== 'undefined') {
element.src = URL.createObjectURL(stream);
} else {
console.error('Error attaching stream to element.');
}
self.options.useAudio.play();
self.remoteStream = stream;
}
function onOfferSDP(self, sdp) {
self.mediaData.SDP = self.stereoHack(sdp.sdp);
console.log("Offer SDP");
doCallback(self, "onOfferSDP");
}
$.FSRTC.prototype.answer = function(sdp, onSuccess, onError) {
this.peer.addAnswerSDP({
type: "answer",
sdp: sdp
},
onSuccess, onError);
};
$.FSRTC.prototype.stop = function() {
var self = this;
if (self.options.useVideo) {
self.options.useVideo.style.display = 'none';
}
if (self.localStream) {
self.localStream.stop();
self.localStream = null;
}
if (self.peer) {
console.log("stopping peer");
self.peer.stop();
}
};
$.FSRTC.prototype.createAnswer = function(sdp) {
var self = this;
self.type = "answer";
self.remoteSDP = sdp;
console.debug("inbound sdp: ", sdp);
function onSuccess(stream) {
self.localStream = stream;
self.peer = RTCPeerConnection({
type: self.type,
attachStream: self.localStream,
onICE: function(candidate) {
return onICE(self, candidate);
},
onICEComplete: function() {
return onICEComplete(self);
},
onRemoteStream: function(stream) {
return onRemoteStream(self, stream);
},
onICESDP: function(sdp) {
return onICESDP(self, sdp);
},
onChannelError: function(e) {
return onChannelError(self, e);
},
constraints: self.constraints,
offerSDP: {
type: "offer",
sdp: self.remoteSDP
}
});
onStreamSuccess(self);
}
function onError() {
onStreamError(self);
}
getUserMedia({
constraints: {
audio: true,
video: this.options.useVideo ? {
mandatory: this.options.videoParams,
optional: []
} : null
},
video: this.options.useVideo ? true : false,
onsuccess: onSuccess,
onerror: onError
});
};
$.FSRTC.prototype.call = function(profile) {
checkCompat();
var self = this;
self.type = "offer";
function onSuccess(stream) {
self.localStream = stream;
self.peer = RTCPeerConnection({
type: self.type,
attachStream: self.localStream,
onICE: function(candidate) {
return onICE(self, candidate);
},
onICEComplete: function() {
return onICEComplete(self);
},
onRemoteStream: function(stream) {
return onRemoteStream(self, stream);
},
onOfferSDP: function(sdp) {
return onOfferSDP(self, sdp);
},
onICESDP: function(sdp) {
return onICESDP(self, sdp);
},
onChannelError: function(e) {
return onChannelError(self, e);
},
constraints: self.constraints
});
onStreamSuccess(self);
}
function onError() {
onStreamError(self);
}
getUserMedia({
constraints: {
audio: true,
video: this.options.useVideo ? {
mandatory: this.options.videoParams,
optional: []
} : null
},
video: this.options.useVideo ? true : false,
onsuccess: onSuccess,
onerror: onError
});
/*
navigator.getUserMedia({
video: this.options.useVideo,
audio: true
}, onSuccess, onError);
*/
};
// DERIVED from RTCPeerConnection-v1.5
// 2013, @muazkh - github.com/muaz-khan
// MIT License - https://www.webrtc-experiment.com/licence/
// Documentation - https://github.com/muaz-khan/WebRTC-Experiment/tree/master/RTCPeerConnection
window.moz = !!navigator.mozGetUserMedia;
function RTCPeerConnection(options) {
var w = window,
PeerConnection = w.mozRTCPeerConnection || w.webkitRTCPeerConnection,
SessionDescription = w.mozRTCSessionDescription || w.RTCSessionDescription,
IceCandidate = w.mozRTCIceCandidate || w.RTCIceCandidate;
var STUN = {
url: !moz ? 'stun:stun.l.google.com:19302' : 'stun:23.21.150.121'
};
var TURN = {
url: 'turn:homeo@turn.bistri.com:80',
credential: 'homeo'
};
var iceServers = {
iceServers: options.iceServers || [STUN]
};
if (!moz && !options.iceServers) {
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];
}
var optional = {
optional: []
};
if (!moz) {
optional.optional = [{
DtlsSrtpKeyAgreement: true
},
{
RtpDataChannels: options.onChannelMessage ? true : false
}];
}
var peer = new PeerConnection(iceServers, optional);
openOffererChannel();
var x = 0;
peer.onicecandidate = function(event) {
if (event.candidate) {
options.onICE(event.candidate);
} else {
if (options.onICEComplete) {
options.onICEComplete();
}
if (options.type == "offer") {
if (!moz && !x && options.onICESDP) {
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);
*/
}
} 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);
*/
}
}
}
};
// attachStream = MediaStream;
if (options.attachStream) peer.addStream(options.attachStream);
// attachStreams[0] = audio-stream;
// attachStreams[1] = video-stream;
// attachStreams[2] = screen-capturing-stream;
if (options.attachStreams && options.attachStream.length) {
var streams = options.attachStreams;
for (var i = 0; i < streams.length; i++) {
peer.addStream(streams[i]);
}
}
peer.onaddstream = function(event) {
var remoteMediaStream = event.stream;
// onRemoteStreamEnded(MediaStream)
remoteMediaStream.onended = function() {
if (options.onRemoteStreamEnded) options.onRemoteStreamEnded(remoteMediaStream);
};
// onRemoteStream(MediaStream)
if (options.onRemoteStream) options.onRemoteStream(remoteMediaStream);
//console.debug('on:add:stream', remoteMediaStream);
};
var constraints = options.constraints || {
optional: [],
mandatory: {
OfferToReceiveAudio: true,
OfferToReceiveVideo: true
}
};
// onOfferSDP(RTCSessionDescription)
function createOffer() {
if (!options.onOfferSDP) return;
peer.createOffer(function(sessionDescription) {
sessionDescription.sdp = serializeSdp(sessionDescription.sdp);
peer.setLocalDescription(sessionDescription);
options.onOfferSDP(sessionDescription);
if (moz && options.onICESDP) {
options.onICESDP(sessionDescription);
}
},
onSdpError, constraints);
}
// onAnswerSDP(RTCSessionDescription)
function createAnswer() {
if (options.type != "answer") return;
//options.offerSDP.sdp = addStereo(options.offerSDP.sdp);
peer.setRemoteDescription(new SessionDescription(options.offerSDP), onSdpSuccess, onSdpError);
peer.createAnswer(function(sessionDescription) {
sessionDescription.sdp = serializeSdp(sessionDescription.sdp);
peer.setLocalDescription(sessionDescription);
if (options.onAnswerSDP) {
options.onAnswerSDP(sessionDescription);
}
},
onSdpError, constraints);
}
// if Mozilla Firefox & DataChannel; offer/answer will be created later
if ((options.onChannelMessage && !moz) || !options.onChannelMessage) {
createOffer();
createAnswer();
}
// DataChannel Bandwidth
function setBandwidth(sdp) {
// remove existing bandwidth lines
sdp = sdp.replace(/b=AS([^\r\n]+\r\n)/g, '');
sdp = sdp.replace(/a=mid:data\r\n/g, 'a=mid:data\r\nb=AS:1638400\r\n');
return sdp;
}
// old: FF<>Chrome interoperability management
function getInteropSDP(sdp) {
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''),
extractedChars = '';
function getChars() {
extractedChars += chars[parseInt(Math.random() * 40)] || '';
if (extractedChars.length < 40) getChars();
return extractedChars;
}
// usually audio-only streaming failure occurs out of audio-specific crypto line
// a=crypto:1 AES_CM_128_HMAC_SHA1_32 --------- kAttributeCryptoVoice
if (options.onAnswerSDP) sdp = sdp.replace(/(a=crypto:0 AES_CM_128_HMAC_SHA1_32)(.*?)(\r\n)/g, '');
// video-specific crypto line i.e. SHA1_80
// a=crypto:1 AES_CM_128_HMAC_SHA1_80 --------- kAttributeCryptoVideo
var inline = getChars() + '\r\n' + (extractedChars = '');
sdp = sdp.indexOf('a=crypto') == -1 ? sdp.replace(/c=IN/g, 'a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:' + inline + 'c=IN') : sdp;
return sdp;
}
function serializeSdp(sdp) {
//if (!moz) sdp = setBandwidth(sdp);
//sdp = getInteropSDP(sdp);
//console.debug(sdp);
return sdp;
}
// DataChannel management
var channel;
function openOffererChannel() {
if (!options.onChannelMessage || (moz && !options.onOfferSDP)) return;
_openOffererChannel();
if (!moz) return;
navigator.mozGetUserMedia({
audio: true,
fake: true
},
function(stream) {
peer.addStream(stream);
createOffer();
},
useless);
}
function _openOffererChannel() {
channel = peer.createDataChannel(options.channel || 'RTCDataChannel', moz ? {} : {
reliable: false
});
if (moz) channel.binaryType = 'blob';
setChannelEvents();
}
function setChannelEvents() {
channel.onmessage = function(event) {
if (options.onChannelMessage) options.onChannelMessage(event);
};
channel.onopen = function() {
if (options.onChannelOpened) options.onChannelOpened(channel);
};
channel.onclose = function(event) {
if (options.onChannelClosed) options.onChannelClosed(event);
console.warn('WebRTC DataChannel closed', event);
};
channel.onerror = function(event) {
if (options.onChannelError) options.onChannelError(event);
console.error('WebRTC DataChannel error', event);
};
}
if (options.onAnswerSDP && moz && options.onChannelMessage) openAnswererChannel();
function openAnswererChannel() {
peer.ondatachannel = function(event) {
channel = event.channel;
channel.binaryType = 'blob';
setChannelEvents();
};
if (!moz) return;
navigator.mozGetUserMedia({
audio: true,
fake: true
},
function(stream) {
peer.addStream(stream);
createAnswer();
},
useless);
}
// fake:true is also available on chrome under a flag!
function useless() {
log('Error in fake:true');
}
function onSdpSuccess() {}
function onSdpError(e) {
if (options.onChannelError) {
options.onChannelError(e);
}
console.error('sdp error:', e);
}
return {
addAnswerSDP: function(sdp, cbSuccess, cbError) {
peer.setRemoteDescription(new SessionDescription(sdp), cbSuccess ? cbSuccess : onSdpSuccess, cbError ? cbError : onSdpError);
},
addICE: function(candidate) {
peer.addIceCandidate(new IceCandidate({
sdpMLineIndex: candidate.sdpMLineIndex,
candidate: candidate.candidate
}));
},
peer: peer,
channel: channel,
sendData: function(message) {
if (channel) {
channel.send(message);
}
},
stop: function() {
peer.close();
if (options.attachStream) {
options.attachStream.stop();
}
}
};
}
// getUserMedia
var video_constraints = {
mandatory: {},
optional: []
};
function getUserMedia(options) {
var n = navigator,
media;
n.getMedia = n.webkitGetUserMedia || n.mozGetUserMedia;
n.getMedia(options.constraints || {
audio: true,
video: video_constraints
},
streaming, options.onerror ||
function(e) {
console.error(e);
});
function streaming(stream) {
var video = options.video;
if (video) {
video[moz ? 'mozSrcObject' : 'src'] = moz ? stream : window.webkitURL.createObjectURL(stream);
//video.play();
}
if (options.onsuccess) {
options.onsuccess(stream);
}
media = stream;
}
return media;
}
})(jQuery);

View File

@ -0,0 +1,653 @@
/*
* Verto HTML5/Javascript Telephony Signaling and Control Protocol Stack for FreeSWITCH
* Copyright (C) 2005-2014, 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 jquery.jsonrpclient.js modified for Verto HTML5/Javascript Telephony Signaling and Control Protocol Stack for FreeSWITCH
*
* The Initial Developer of the Original Code is
* Textalk AB http://textalk.se/
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
*
* jquery.jsonrpclient.js - JSON RPC client code
*
*/
/**
* This plugin requires jquery.json.js to be available, or at least the methods $.toJSON and
* $.parseJSON.
*
* The plan is to make use of websockets if they are available, but work just as well with only
* http if not.
*
* Usage example:
*
* var foo = new $.JsonRpcClient({ ajaxUrl: '/backend/jsonrpc' });
* foo.call(
* 'bar', [ 'A parameter', 'B parameter' ],
* function(result) { alert('Foo bar answered: ' + result.my_answer); },
* function(error) { console.log('There was an error', error); }
* );
*
* More examples are available in README.md
*/
(function($) {
/**
* @fn new
* @memberof $.JsonRpcClient
*
* @param options An object stating the backends:
* ajaxUrl A url (relative or absolute) to a http(s) backend.
* socketUrl A url (relative of absolute) to a ws(s) backend.
* onmessage A socket message handler for other messages (non-responses).
* getSocket A function returning a WebSocket or null.
* It must take an onmessage_cb and bind it to the onmessage event
* (or chain it before/after some other onmessage handler).
* Or, it could return null if no socket is available.
* The returned instance must have readyState <= 1, and if less than 1,
* react to onopen binding.
*/
$.JsonRpcClient = function(options) {
var self = this;
this.options = $.extend({
ajaxUrl : null,
socketUrl : null, ///< The ws-url for default getSocket.
onmessage : null, ///< Other onmessage-handler.
login : null, /// auth login
passwd : null, /// auth passwd
sessid : null,
getSocket : function(onmessage_cb) { return self._getSocket(onmessage_cb); }
}, options);
// Declare an instance version of the onmessage callback to wrap 'this'.
this.wsOnMessage = function(event) { self._wsOnMessage(event); };
};
/// Holding the WebSocket on default getsocket.
$.JsonRpcClient.prototype._ws_socket = null;
/// Object <id>: { success_cb: cb, error_cb: cb }
$.JsonRpcClient.prototype._ws_callbacks = {};
/// The next JSON-RPC request id.
$.JsonRpcClient.prototype._current_id = 1;
/**
* @fn call
* @memberof $.JsonRpcClient
*
* @param method The method to run on JSON-RPC server.
* @param params The params; an array or object.
* @param success_cb A callback for successful request.
* @param error_cb A callback for error.
*/
$.JsonRpcClient.prototype.call = function(method, params, success_cb, error_cb) {
// Construct the JSON-RPC 2.0 request.
if (!params) {
params = {};
}
if (this.options.sessid) {
params.sessid = this.options.sessid;
}
var request = {
jsonrpc : '2.0',
method : method,
params : params,
id : this._current_id++ // Increase the id counter to match request/response
};
if (!success_cb) {
success_cb = function(e){console.log("Success: ", e);};
}
if (!error_cb) {
error_cb = function(e){console.log("Error: ", e);};
}
// Try making a WebSocket call.
var socket = this.options.getSocket(this.wsOnMessage);
if (socket !== null) {
this._wsCall(socket, request, success_cb, error_cb);
return;
}
// No WebSocket, and no HTTP backend? This won't work.
if (this.options.ajaxUrl === null) {
throw "$.JsonRpcClient.call used with no websocket and no http endpoint.";
}
$.ajax({
type : 'POST',
url : this.options.ajaxUrl,
data : $.toJSON(request),
dataType : 'json',
cache : false,
success : function(data) {
if ('error' in data) error_cb(data.error, this);
success_cb(data.result, this);
},
// JSON-RPC Server could return non-200 on error
error : function(jqXHR, textStatus, errorThrown) {
try {
var response = $.parseJSON(jqXHR.responseText);
if ('console' in window) console.log(response);
error_cb(response.error, this);
}
catch (err) {
// Perhaps the responseText wasn't really a jsonrpc-error.
error_cb({ error: jqXHR.responseText }, this);
}
}
});
};
/**
* Notify sends a command to the server that won't need a response. In http, there is probably
* an empty response - that will be dropped, but in ws there should be no response at all.
*
* This is very similar to call, but has no id and no handling of callbacks.
*
* @fn notify
* @memberof $.JsonRpcClient
*
* @param method The method to run on JSON-RPC server.
* @param params The params; an array or object.
*/
$.JsonRpcClient.prototype.notify = function(method, params) {
// Construct the JSON-RPC 2.0 request.
if (this.options.sessid) {
params.sessid = this.options.sessid;
}
var request = {
jsonrpc: '2.0',
method: method,
params: params
};
// Try making a WebSocket call.
var socket = this.options.getSocket(this.wsOnMessage);
if (socket !== null) {
this._wsCall(socket, request);
return;
}
// No WebSocket, and no HTTP backend? This won't work.
if (this.options.ajaxUrl === null) {
throw "$.JsonRpcClient.notify used with no websocket and no http endpoint.";
}
$.ajax({
type : 'POST',
url : this.options.ajaxUrl,
data : $.toJSON(request),
dataType : 'json',
cache : false
});
};
/**
* Make a batch-call by using a callback.
*
* The callback will get an object "batch" as only argument. On batch, you can call the methods
* "call" and "notify" just as if it was a normal $.JsonRpcClient object, and all calls will be
* sent as a batch call then the callback is done.
*
* @fn batch
* @memberof $.JsonRpcClient
*
* @param callback The main function which will get a batch handler to run call and notify on.
* @param all_done_cb A callback function to call after all results have been handled.
* @param error_cb A callback function to call if there is an error from the server.
* Note, that batch calls should always get an overall success, and the
* only error
*/
$.JsonRpcClient.prototype.batch = function(callback, all_done_cb, error_cb) {
var batch = new $.JsonRpcClient._batchObject(this, all_done_cb, error_cb);
callback(batch);
batch._execute();
};
/**
* The default getSocket handler.
*
* @param onmessage_cb The callback to be bound to onmessage events on the socket.
*
* @fn _getSocket
* @memberof $.JsonRpcClient
*/
$.JsonRpcClient.prototype.socketReady = function() {
if (this._ws_socket === null || this._ws_socket.readyState > 1) {
return false;
}
return true;
}
$.JsonRpcClient.prototype.closeSocket = function() {
if (self.socketReady()) {
this._ws_socket.onclose = function (w) {console.log("Closing Socket")}
this._ws_socket.close();
}
}
$.JsonRpcClient.prototype.loginData = function(params) {
self.options.login = params.login;
self.options.passwd = params.passwd;
}
$.JsonRpcClient.prototype.connectSocket = function(onmessage_cb) {
var self = this;
if (!self.socketReady()) {
self.authing = false;
// No socket, or dying socket, let's get a new one.
this._ws_socket = new WebSocket(this.options.socketUrl);
if (this._ws_socket) {
// Set up onmessage handler.
this._ws_socket.onmessage = onmessage_cb;
this._ws_socket.onclose = function (w) {
if (!self.ws_sleep) {
self.ws_sleep = 2;
}
self.ws_cnt = 0;
if (self.options.onWSClose) {
self.options.onWSClose(self);
}
console.error("Websocket Lost sleep: " + self.ws_sleep + "sec");
setTimeout(function() {
console.log("Attempting Reconnection....");
self.connectSocket(onmessage_cb);
}, self.ws_sleep * 1000);
if (++self.ws_cnt >= 150) {
self.ws_sleep = 30;
}
}
// Set up sending of message for when the socket is open.
this._ws_socket.onopen = function() {
this.ws_sleep = 2;
this.ws_cnt = 0;
if (self.options.onWSConnect) {
self.options.onWSConnect(self);
}
var req;
// Send the requests.
while (req = $.JsonRpcClient.q.pop()) {
self._ws_socket.send(req);
}
}
}
}
return this._ws_socket ? true : false;
}
$.JsonRpcClient.prototype._getSocket = function(onmessage_cb) {
// If there is no ws url set, we don't have a socket.
// Likewise, if there is no window.WebSocket.
if (this.options.socketUrl === null || !("WebSocket" in window)) return null;
this.connectSocket(onmessage_cb);
return this._ws_socket;
};
/**
* Queue to save messages delivered when websocket is not ready
*/
$.JsonRpcClient.q = [];
/**
* Internal handler to dispatch a JRON-RPC request through a websocket.
*
* @fn _wsCall
* @memberof $.JsonRpcClient
*/
$.JsonRpcClient.prototype._wsCall = function(socket, request, success_cb, error_cb) {
var request_json = $.toJSON(request);
if (socket.readyState < 1) {
// The websocket is not open yet; we have to set sending of the message in onopen.
self = this; // In closure below, this is set to the WebSocket. Use self instead.
$.JsonRpcClient.q.push(request_json);
}
else {
// We have a socket and it should be ready to send on.
socket.send(request_json);
}
// Setup callbacks. If there is an id, this is a call and not a notify.
if ('id' in request && typeof success_cb !== 'undefined') {
this._ws_callbacks[request.id] = { request: request_json, request_obj: request, success_cb: success_cb, error_cb: error_cb };
}
};
/**
* Internal handler for the websocket messages. It determines if the message is a JSON-RPC
* response, and if so, tries to couple it with a given callback. Otherwise, it falls back to
* given external onmessage-handler, if any.
*
* @param event The websocket onmessage-event.
*/
$.JsonRpcClient.prototype._wsOnMessage = function(event) {
// Check if this could be a JSON RPC message.
var response;
try {
response = $.parseJSON(event.data);
/// @todo Make using the jsonrcp 2.0 check optional, to use this on JSON-RPC 1 backends.
if (typeof response === 'object'
&& 'jsonrpc' in response
&& response.jsonrpc === '2.0') {
/// @todo Handle bad response (without id).
// If this is an object with result, it is a response.
if ('result' in response && this._ws_callbacks[response.id]) {
// Get the success callback.
var success_cb = this._ws_callbacks[response.id].success_cb;
/*
// set the sessid if present
if ('sessid' in response.result && !this.options.sessid || (this.options.sessid != response.result.sessid)) {
this.options.sessid = response.result.sessid;
if (this.options.sessid) {
console.log("setting session UUID to: " + this.options.sessid);
}
}
*/
// Delete the callback from the storage.
delete this._ws_callbacks[response.id];
// Run callback with result as parameter.
success_cb(response.result, this);
return;
}
// If this is an object with error, it is an error response.
else if ('error' in response && this._ws_callbacks[response.id]) {
// Get the error callback.
var error_cb = this._ws_callbacks[response.id].error_cb;
var orig_req = this._ws_callbacks[response.id].request;
// if this is an auth request, send the credentials and resend the failed request
if (!self.authing && response.error.code == -32000 && self.options.login && self.options.passwd) {
self.authing = true;
this.call("login", { login: self.options.login, passwd: self.options.passwd},
this._ws_callbacks[response.id].request_obj.method == "login"
?
function(e) {
self.authing = false;
console.log("logged in");
delete self._ws_callbacks[response.id];
if (self.options.onWSLogin) {
self.options.onWSLogin(true, self);
}
}
:
function(e) {
self.authing = false;
console.log("logged in, resending request id: " + response.id);
var socket = self.options.getSocket(self.wsOnMessage);
if (socket !== null) {
socket.send(orig_req);
}
if (self.options.onWSLogin) {
self.options.onWSLogin(true, self);
}
},
function(e) {
console.log("error logging in, request id:", response.id);
delete self._ws_callbacks[response.id];
error_cb(response.error, this);
if (self.options.onWSLogin) {
self.options.onWSLogin(false, self);
}
}
);
return;
}
// Delete the callback from the storage.
delete this._ws_callbacks[response.id];
// Run callback with the error object as parameter.
error_cb(response.error, this);
return;
}
}
}
catch (err) {
// Probably an error while parsing a non json-string as json. All real JSON-RPC cases are
// handled above, and the fallback method is called below.
console.log("ERROR: "+ err);
return;
}
// This is not a JSON-RPC response. Call the fallback message handler, if given.
if (typeof this.options.onmessage === 'function') {
event.eventData = response;
if (!event.eventData) {
event.eventData = {};
}
var reply = this.options.onmessage(event);
if (reply && typeof reply === "object" && event.eventData.id) {
var msg = {
jsonrpc: "2.0",
id: event.eventData.id,
result: reply
};
var socket = self.options.getSocket(self.wsOnMessage);
if (socket !== null) {
socket.send($.toJSON(msg));
}
}
}
};
/************************************************************************************************
* Batch object with methods
************************************************************************************************/
/**
* Handling object for batch calls.
*/
$.JsonRpcClient._batchObject = function(jsonrpcclient, all_done_cb, error_cb) {
// Array of objects to hold the call and notify requests. Each objects will have the request
// object, and unless it is a notify, success_cb and error_cb.
this._requests = [];
this.jsonrpcclient = jsonrpcclient;
this.all_done_cb = all_done_cb;
this.error_cb = typeof error_cb === 'function' ? error_cb : function() {};
};
/**
* @sa $.JsonRpcClient.prototype.call
*/
$.JsonRpcClient._batchObject.prototype.call = function(method, params, success_cb, error_cb) {
if (!params) {
params = {};
}
if (this.options.sessid) {
params.sessid = this.options.sessid;
}
if (!success_cb) {
success_cb = function(e){console.log("Success: ", e);};
}
if (!error_cb) {
error_cb = function(e){console.log("Error: ", e);};
}
this._requests.push({
request : {
jsonrpc : '2.0',
method : method,
params : params,
id : this.jsonrpcclient._current_id++ // Use the client's id series.
},
success_cb : success_cb,
error_cb : error_cb
});
};
/**
* @sa $.JsonRpcClient.prototype.notify
*/
$.JsonRpcClient._batchObject.prototype.notify = function(method, params) {
if (this.options.sessid) {
params.sessid = this.options.sessid;
}
this._requests.push({
request : {
jsonrpc : '2.0',
method : method,
params : params
}
});
};
/**
* Executes the batched up calls.
*/
$.JsonRpcClient._batchObject.prototype._execute = function() {
var self = this;
if (this._requests.length === 0) return; // All done :P
// Collect all request data and sort handlers by request id.
var batch_request = [];
var handlers = {};
// If we have a WebSocket, just send the requests individually like normal calls.
var socket = self.jsonrpcclient.options.getSocket(self.jsonrpcclient.wsOnMessage);
if (socket !== null) {
for (var i = 0; i < this._requests.length; i++) {
var call = this._requests[i];
var success_cb = ('success_cb' in call) ? call.success_cb : undefined;
var error_cb = ('error_cb' in call) ? call.error_cb : undefined;
self.jsonrpcclient._wsCall(socket, call.request, success_cb, error_cb);
}
if (typeof all_done_cb === 'function') all_done_cb(result);
return;
}
for (var i = 0; i < this._requests.length; i++) {
var call = this._requests[i];
batch_request.push(call.request);
// If the request has an id, it should handle returns (otherwise it's a notify).
if ('id' in call.request) {
handlers[call.request.id] = {
success_cb : call.success_cb,
error_cb : call.error_cb
};
}
}
var success_cb = function(data) { self._batchCb(data, handlers, self.all_done_cb); };
// No WebSocket, and no HTTP backend? This won't work.
if (self.jsonrpcclient.options.ajaxUrl === null) {
throw "$.JsonRpcClient.batch used with no websocket and no http endpoint.";
}
// Send request
$.ajax({
url : self.jsonrpcclient.options.ajaxUrl,
data : $.toJSON(batch_request),
dataType : 'json',
cache : false,
type : 'POST',
// Batch-requests should always return 200
error : function(jqXHR, textStatus, errorThrown) {
self.error_cb(jqXHR, textStatus, errorThrown);
},
success : success_cb
});
};
/**
* Internal helper to match the result array from a batch call to their respective callbacks.
*
* @fn _batchCb
* @memberof $.JsonRpcClient
*/
$.JsonRpcClient._batchObject.prototype._batchCb = function(result, handlers, all_done_cb) {
for (var i = 0; i < result.length; i++) {
var response = result[i];
// Handle error
if ('error' in response) {
if (response.id === null || !(response.id in handlers)) {
// An error on a notify? Just log it to the console.
if ('console' in window) console.log(response);
}
else handlers[response.id].error_cb(response.error, this);
}
else {
// Here we should always have a correct id and no error.
if (!(response.id in handlers) && 'console' in window) console.log(response);
else handlers[response.id].success_cb(response.result, this);
}
}
if (typeof all_done_cb === 'function') all_done_cb(result);
};
})(jQuery);

File diff suppressed because it is too large Load Diff

1
libs/.gitignore vendored
View File

@ -835,3 +835,4 @@ unimrcp/build/compile
/curl-*/
/sqlite-*.zip
/sqlite-*/
/ldns/

View File

@ -59,6 +59,7 @@ typedef struct {
const char *console_fnkeys[12];
char loglevel[128];
int log_uuid;
int log_uuid_length;
int quiet;
int batch_mode;
char prompt_color[12];
@ -66,6 +67,7 @@ typedef struct {
char output_text_color[12];
} cli_profile_t;
static const int log_uuid_short_length = 8;
static int is_color = 1;
static int warn_stop = 0;
static int connected = 0;
@ -604,6 +606,7 @@ static const char *usage_str =
" -x, --execute=command Execute Command and Exit\n"
" -l, --loglevel=command Log Level\n"
" -U, --log-uuid Include UUID in log output\n"
" -S, --log-uuid-short Include shortened UUID in log output\n"
" -q, --quiet Disable logging\n"
" -r, --retry Retry connection on failure\n"
" -R, --reconnect Reconnect if disconnected\n"
@ -742,7 +745,16 @@ static void *msg_thread_run(esl_thread_t *me, void *obj)
printf("%s", colors[level]);
}
if (global_profile->log_uuid && !esl_strlen_zero(userdata)) {
printf("%s ", userdata);
if (global_profile->log_uuid_length) {
int len = strlen(userdata);
int i = (global_profile->log_uuid_length < len) ? global_profile->log_uuid_length : len;
if (fwrite(userdata, sizeof(char), i, stdout) < i) {
// don't care
}
printf(" ");
} else {
printf("%s ", userdata);
}
}
if (strcmp("\n",handle->last_event->body)) {
char *c = handle->last_event->body;
@ -1235,6 +1247,14 @@ static void read_config(const char *dft_cfile, const char *cfile) {
esl_set_string(profiles[pcount-1].loglevel, val);
} else if(!strcasecmp(var, "log-uuid")) {
profiles[pcount-1].log_uuid = esl_true(val);
} else if(!strcasecmp(var, "log-uuid-short")) {
profiles[pcount-1].log_uuid = esl_true(val);
profiles[pcount-1].log_uuid_length = (esl_true(val) ? log_uuid_short_length : 0);
} else if(!strcasecmp(var, "log-uuid-length")) {
int i;
if ((i = atoi(val)) > -1) {
profiles[pcount-1].log_uuid_length = i;
}
} else if(!strcasecmp(var, "quiet")) {
profiles[pcount-1].quiet = esl_true(val);
} else if(!strcasecmp(var, "prompt-color")) {
@ -1301,6 +1321,7 @@ int main(int argc, char *argv[])
{"execute", 1, 0, 'x'},
{"loglevel", 1, 0, 'l'},
{"log-uuid", 0, 0, 'U'},
{"log-uuid-short", 0, 0, 'S'},
{"quiet", 0, 0, 'q'},
{"batchmode", 0, 0, 'b'},
{"retry", 0, 0, 'r'},
@ -1324,6 +1345,7 @@ int main(int argc, char *argv[])
char argv_command[1024] = "";
char argv_loglevel[128] = "";
int argv_log_uuid = 0;
int argv_log_uuid_short = 0;
int argv_quiet = 0;
int argv_batch = 0;
int loops = 2, reconnect = 0;
@ -1373,7 +1395,7 @@ int main(int argc, char *argv[])
esl_global_set_default_logger(6); /* default debug level to 6 (info) */
for(;;) {
int option_index = 0;
opt = getopt_long(argc, argv, "H:P:S:u:p:d:x:l:Ut:T:qrRhib?n", options, &option_index);
opt = getopt_long(argc, argv, "H:P:u:p:d:x:l:USt:T:qrRhib?n", options, &option_index);
if (opt == -1) break;
switch (opt) {
case 'H':
@ -1419,6 +1441,9 @@ int main(int argc, char *argv[])
case 'U':
argv_log_uuid = 1;
break;
case 'S':
argv_log_uuid_short = 1;
break;
case 'q':
argv_quiet = 1;
break;
@ -1487,6 +1512,10 @@ int main(int argc, char *argv[])
if (argv_log_uuid) {
profile->log_uuid = 1;
}
if (argv_log_uuid_short) {
profile->log_uuid = 1;
profile->log_uuid_length = log_uuid_short_length;
}
esl_log(ESL_LOG_DEBUG, "Using profile %s [%s]\n", profile->name, profile->host);
esl_set_string(prompt_color, profile->prompt_color);
esl_set_string(input_text_color, profile->input_text_color);

View File

@ -12,9 +12,9 @@ perlmod: ESL.la
install-data-local: perlmod-install
perlmod-install: install-perlLTLIBRARIES
install -m 755 ESL.pm $(PERL_SITEDIR)
install -d -m 755 ESL $(PERL_SITEDIR)/ESL
install -m 755 ESL/* $(PERL_SITEDIR)/ESL
install -d -m 755 ESL $(DESTDIR)$(PERL_SITEDIR)/ESL
install -m 755 ESL.pm $(DESTDIR)$(PERL_SITEDIR)
install -m 755 ESL/* $(DESTDIR)$(PERL_SITEDIR)/ESL
endif
esl_wrap.cpp:

View File

@ -81,28 +81,30 @@ extern "C" {
\param expr a string expression
\return true or false
*/
#define esl_true(expr)\
(expr && ( !strcasecmp(expr, "yes") ||\
!strcasecmp(expr, "on") ||\
!strcasecmp(expr, "true") ||\
!strcasecmp(expr, "enabled") ||\
!strcasecmp(expr, "active") ||\
!strcasecmp(expr, "allow") ||\
atoi(expr))) ? 1 : 0
static __inline__ int esl_true(const char *expr) {
return (expr && (!strcasecmp(expr, "yes")
|| !strcasecmp(expr, "on")
|| !strcasecmp(expr, "true")
|| !strcasecmp(expr, "enabled")
|| !strcasecmp(expr, "active")
|| !strcasecmp(expr, "allow")
|| atoi(expr)));
}
/*!
\brief Evaluate the falsefullness of a string expression
\param expr a string expression
\return true or false
*/
#define esl_false(expr)\
(expr && ( !strcasecmp(expr, "no") ||\
!strcasecmp(expr, "off") ||\
!strcasecmp(expr, "false") ||\
!strcasecmp(expr, "disabled") ||\
!strcasecmp(expr, "inactive") ||\
!strcasecmp(expr, "disallow") ||\
!atoi(expr))) ? 1 : 0
static __inline__ int esl_false(const char *expr) {
return (expr && (!strcasecmp(expr, "no")
|| !strcasecmp(expr, "off")
|| !strcasecmp(expr, "false")
|| !strcasecmp(expr, "disabled")
|| !strcasecmp(expr, "inactive")
|| !strcasecmp(expr, "disallow")
|| !atoi(expr)));
}
typedef struct esl_config esl_config_t;

View File

@ -5538,6 +5538,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_freetdm_shutdown)
ftdm_conf_node_destroy(val);
}
switch_core_hash_destroy(&globals.ss7_configs);
ftdm_global_destroy();
// this breaks pika but they are MIA so *shrug*

View File

@ -59,6 +59,8 @@ struct tm *localtime_r(const time_t *clock, struct tm *result);
#define FTDM_HALF_DTMF_PAUSE 500
#define FTDM_FULL_DTMF_PAUSE 1000
#define FTDM_CHANNEL_SW_DTMF_ALLOWED(ftdmchan) (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT) && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_DTMF_DETECTION))
ftdm_time_t time_last_throttle_log = 0;
ftdm_time_t time_current_throttle_log = 0;
@ -105,6 +107,7 @@ static val_str_t channel_flag_strs[] = {
{ "blocking", FTDM_CHANNEL_BLOCKING},
{ "media", FTDM_CHANNEL_DIGITAL_MEDIA},
{ "native-sigbridge", FTDM_CHANNEL_NATIVE_SIGBRIDGE},
{ "sig-dtmf-detection", FTDM_CHANNEL_SIG_DTMF_DETECTION},
{ "invalid", FTDM_CHANNEL_MAX_FLAG},
};
@ -690,15 +693,11 @@ static ftdm_status_t ftdm_span_destroy(ftdm_span_t *span)
ftdm_status_t status = FTDM_SUCCESS;
unsigned j;
/* The signaling must be already stopped (this is just a sanity check, should never happen) */
ftdm_assert_return(!ftdm_test_flag(span, FTDM_SPAN_STARTED), FTDM_FAIL, "Signaling for span %s has not been stopped, refusing to destroy span\n");
ftdm_mutex_lock(span->mutex);
/* stop the signaling */
/* This is a forced stopped */
ftdm_clear_flag(span, FTDM_SPAN_NON_STOPPABLE);
ftdm_span_stop(span);
/* destroy the channels */
ftdm_clear_flag(span, FTDM_SPAN_CONFIGURED);
for(j = 1; j <= span->chan_count && span->channels[j]; j++) {
@ -3374,7 +3373,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
{
/* if they don't have thier own, use ours */
if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) {
if (FTDM_CHANNEL_SW_DTMF_ALLOWED(ftdmchan)) {
teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate);
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT);
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF);
@ -3387,9 +3386,9 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
case FTDM_COMMAND_DISABLE_DTMF_DETECT:
{
if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) {
teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT);
if (FTDM_CHANNEL_SW_DTMF_ALLOWED(ftdmchan)) {
teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF);
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Disabled software DTMF detector\n");
GOTO_STATUS(done, FTDM_SUCCESS);
@ -3465,8 +3464,11 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
break;
case FTDM_COMMAND_SEND_DTMF:
{
if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_GENERATE)) {
char *digits = FTDM_COMMAND_OBJ_CHAR_P;
char *digits = FTDM_COMMAND_OBJ_CHAR_P;
if (ftdmchan->span->sig_send_dtmf) {
status = ftdmchan->span->sig_send_dtmf(ftdmchan, digits);
GOTO_STATUS(done, status);
} else if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_GENERATE)) {
if ((status = ftdmchan_activate_dtmf_buffer(ftdmchan)) != FTDM_SUCCESS) {
GOTO_STATUS(done, status);
@ -3777,7 +3779,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, cons
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Queuing DTMF %s (debug = %d)\n", dtmf, ftdmchan->dtmfdbg.enabled);
if (ftdmchan->span->sig_dtmf && (ftdmchan->span->sig_dtmf(ftdmchan, dtmf) == FTDM_BREAK)) {
if (ftdmchan->span->sig_queue_dtmf && (ftdmchan->span->sig_queue_dtmf(ftdmchan, dtmf) == FTDM_BREAK)) {
/* Signalling module wants to absorb this DTMF event */
return FTDM_SUCCESS;
}
@ -4216,7 +4218,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, v
}
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT) && !ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) {
if (FTDM_CHANNEL_SW_DTMF_ALLOWED(ftdmchan) && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT)) {
teletone_hit_type_t hit;
char digit_char;
uint32_t dur;
@ -6040,6 +6042,17 @@ FT_DECLARE(ftdm_status_t) ftdm_group_create(ftdm_group_t **group, const char *na
return status;
}
static void ftdm_group_destroy(ftdm_group_t **group)
{
ftdm_group_t *grp = NULL;
ftdm_assert(group != NULL, "Group must not be null\n");
grp = *group;
ftdm_mutex_destroy(&grp->mutex);
ftdm_safe_free(grp->name);
ftdm_safe_free(grp);
*group = NULL;
}
static ftdm_status_t ftdm_span_trigger_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
{
if (!span->signal_cb) {
@ -6376,10 +6389,37 @@ FT_DECLARE(uint32_t) ftdm_running(void)
return globals.running;
}
static void destroy_span(ftdm_span_t *span)
{
if (ftdm_test_flag(span, FTDM_SPAN_CONFIGURED)) {
ftdm_span_destroy(span);
}
hashtable_remove(globals.span_hash, (void *)span->name);
ftdm_safe_free(span->dtmf_hangup);
ftdm_safe_free(span->type);
ftdm_safe_free(span->name);
ftdm_safe_free(span);
}
static void force_stop_span(ftdm_span_t *span)
{
/* This is a forced stop */
ftdm_clear_flag(span, FTDM_SPAN_NON_STOPPABLE);
ftdm_span_stop(span);
}
static void span_for_each(void (*func)(ftdm_span_t *span))
{
ftdm_span_t *sp = NULL, *next = NULL;
for (sp = globals.spans; sp; sp = next) {
next = sp->next;
func(sp);
}
}
FT_DECLARE(ftdm_status_t) ftdm_global_destroy(void)
{
ftdm_span_t *sp;
ftdm_group_t *grp = NULL, *next_grp = NULL;
time_end();
@ -6397,45 +6437,49 @@ FT_DECLARE(ftdm_status_t) ftdm_global_destroy(void)
ftdm_span_close_all();
/* Stop and destroy alls pans */
ftdm_mutex_lock(globals.span_mutex);
for (sp = globals.spans; sp;) {
ftdm_span_t *cur_span = sp;
sp = sp->next;
if (cur_span) {
if (ftdm_test_flag(cur_span, FTDM_SPAN_CONFIGURED)) {
ftdm_span_destroy(cur_span);
}
hashtable_remove(globals.span_hash, (void *)cur_span->name);
ftdm_safe_free(cur_span->dtmf_hangup);
ftdm_safe_free(cur_span->type);
ftdm_safe_free(cur_span->name);
ftdm_safe_free(cur_span);
cur_span = NULL;
}
}
span_for_each(force_stop_span);
span_for_each(destroy_span);
globals.spans = NULL;
ftdm_mutex_unlock(globals.span_mutex);
/* destroy signaling and io modules */
ftdm_unload_modules();
ftdm_global_set_logger( NULL );
/* Destroy hunting groups */
ftdm_mutex_lock(globals.group_mutex);
grp = globals.groups;
while (grp) {
next_grp = grp->next;
ftdm_group_destroy(&grp);
grp = next_grp;
}
ftdm_mutex_unlock(globals.group_mutex);
/* finally destroy the globals */
ftdm_mutex_lock(globals.mutex);
ftdm_sched_destroy(&globals.timingsched);
hashtable_destroy(globals.interface_hash);
hashtable_destroy(globals.module_hash);
hashtable_destroy(globals.span_hash);
hashtable_destroy(globals.group_hash);
ftdm_mutex_unlock(globals.mutex);
ftdm_mutex_destroy(&globals.mutex);
ftdm_mutex_destroy(&globals.span_mutex);
ftdm_mutex_destroy(&globals.group_mutex);
ftdm_mutex_destroy(&globals.call_id_mutex);
ftdm_mutex_unlock(globals.mutex);
ftdm_mutex_destroy(&globals.mutex);
ftdm_sched_global_destroy();
ftdm_global_set_logger(NULL);
memset(&globals, 0, sizeof(globals));
return FTDM_SUCCESS;
}

View File

@ -166,6 +166,13 @@ FT_DECLARE(ftdm_status_t) ftdm_sched_global_init()
return FTDM_FAIL;
}
FT_DECLARE(ftdm_status_t) ftdm_sched_global_destroy()
{
ftdm_mutex_destroy(&sched_globals.mutex);
memset(&sched_globals, 0, sizeof(sched_globals));
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) ftdm_sched_free_run(ftdm_sched_t *sched)
{
ftdm_status_t status = FTDM_FAIL;

View File

@ -60,18 +60,6 @@
#include <private/ftdm_core.h>
// Debug
#define LOG_SIG_DATA 0
#define DEBUG_STATES 0
#if DEBUG_STATES // state debugging
#define STATE_ADVANCE_LOG_LEVEL FTDM_LOG_CRIT
#else
#define STATE_ADVANCE_LOG_LEVEL FTDM_LOG_DEBUG
#endif
/********************************************************************************/
/* */
/* MACROS */
@ -177,7 +165,6 @@ static ftdm_io_interface_t g_ftdm_gsm_interface;
/********************************************************************************/
static int read_channel(ftdm_channel_t *ftdm_chan , const void *buf, int size)
{
ftdm_size_t outsize = size;
ftdm_status_t status = ftdm_channel_read(ftdm_chan, (void *)buf, &outsize);
if (FTDM_FAIL == status) {
@ -189,11 +176,6 @@ static int read_channel(ftdm_channel_t *ftdm_chan , const void *buf, int size)
int on_wat_span_write(unsigned char span_id, void *buffer, unsigned len)
{
#if LOG_SIG_DATA
fprintf(stdout, " Out Data ====================>>> %s \r\n (%d) - %d\n", (char *)buffer, len, (int) span_id);
#endif
ftdm_span_t *span = NULL;
ftdm_status_t status = FTDM_FAIL;
ftdm_gsm_span_data_t *gsm_data = NULL;
@ -211,15 +193,7 @@ int on_wat_span_write(unsigned char span_id, void *buffer, unsigned len)
ftdm_log(FTDM_LOG_ERROR, "Failed to write %d bytes to d-channel in span %s\n", len, span->name);
return -1;
}
//#if LOG_SIG_DATA
// fprintf(stdout, "\r\n==================== len=%d outsize=%d \r\n", len, (int)outsize);
//#endif
fflush(stdout);
return len;
}
static void on_wat_span_status(unsigned char span_id, wat_span_status_t *status)
@ -260,9 +234,7 @@ static void on_wat_span_status(unsigned char span_id, wat_span_status_t *status)
void on_wat_con_ind(unsigned char span_id, uint8_t call_id, wat_con_event_t *con_event)
{
ftdm_span_t *span = NULL;
//ftdm_status_t ftdm_status = FTDM_FAIL;
ftdm_gsm_span_data_t *gsm_data = NULL;
//fprintf(stdout, "s%d: Incoming call (id:%d) Calling Number:%s Calling Name:\"%s\" type:%d plan:%d\n", span_id, call_id, con_event->calling_num.digits, con_event->calling_name, con_event->calling_num.type, con_event->calling_num.plan);
ftdm_log(FTDM_LOG_INFO, "s%d: Incoming call (id:%d) Calling Number:%s Calling Name:\"%s\" type:%d plan:%d\n", span_id, call_id, con_event->calling_num.digits, con_event->calling_name, con_event->calling_num.type, con_event->calling_num.plan);
@ -404,8 +376,6 @@ void on_wat_rel_cfm(unsigned char span_id, uint8_t call_id)
void on_wat_sms_ind(unsigned char span_id, wat_sms_event_t *sms_event)
{
//printf("on_wat_sms_ind\r\n");
ftdm_span_t *span = NULL;
ftdm_channel_t *ftdmchan;
@ -431,7 +401,6 @@ void on_wat_sms_ind(unsigned char span_id, wat_sms_event_t *sms_event)
gsm_data->dchan->caller_data.priv = (void *)&sms_data;
ftdm_span_send_signal(span, &sigev);
}
// SEND_STATE_SIGNAL(FTDM_SIGEVENT_SMS);
return;
}
@ -450,26 +419,35 @@ void on_wat_sms_sts(unsigned char span_id, uint8_t sms_id, wat_sms_status_t *sta
return;
}
static void on_wat_dtmf_ind(unsigned char span_id, const char *dtmf)
{
ftdm_span_t *span = NULL;
ftdm_gsm_span_data_t *gsm_data = NULL;
if (!(span = GetSpanByID(span_id, &gsm_data))) {
return;
}
ftdm_channel_queue_dtmf(gsm_data->bchan, dtmf);
}
void on_wat_log(uint8_t level, char *fmt, ...)
{
int ftdm_level;
char buff[10001];
char buff[4096];
va_list argptr;
va_start(argptr, fmt);
switch(level) {
case WAT_LOG_CRIT: ftdm_level = FTDM_LOG_LEVEL_CRIT; break;
case WAT_LOG_ERROR: ftdm_level = FTDM_LOG_LEVEL_ERROR; break;
default:
case WAT_LOG_CRIT: ftdm_level = FTDM_LOG_LEVEL_CRIT; break;
case WAT_LOG_ERROR: ftdm_level = FTDM_LOG_LEVEL_ERROR; break;
case WAT_LOG_WARNING: ftdm_level = FTDM_LOG_LEVEL_WARNING; break;
case WAT_LOG_INFO: ftdm_level = FTDM_LOG_LEVEL_INFO; break;
case WAT_LOG_INFO: ftdm_level = FTDM_LOG_LEVEL_INFO; break;
case WAT_LOG_NOTICE: ftdm_level = FTDM_LOG_LEVEL_NOTICE; break;
case WAT_LOG_DEBUG: ftdm_level = FTDM_LOG_LEVEL_DEBUG; break;
case WAT_LOG_DEBUG: ftdm_level = FTDM_LOG_LEVEL_DEBUG; break;
default: ftdm_level = FTDM_LOG_LEVEL_ERROR; break;
};
@ -498,32 +476,33 @@ void on_wat_free(void *ptr)
void on_wat_log_span(uint8_t span_id, uint8_t level, char *fmt, ...)
{
#if 0
ftdm_span_t *span = NULL;
ftdm_gsm_span_data_t *gsm_data = NULL;
int ftdm_level;
return;
char buff[4096];
va_list argptr;
if (!(span = GetSpanByID(span_id, &gsm_data))) {
return;
}
va_start(argptr, fmt);
char buff[10001];
switch(level) {
case WAT_LOG_CRIT: ftdm_level = FTDM_LOG_LEVEL_CRIT; break;
case WAT_LOG_ERROR: ftdm_level = FTDM_LOG_LEVEL_ERROR; break;
default:
case WAT_LOG_CRIT: ftdm_level = FTDM_LOG_LEVEL_CRIT; break;
case WAT_LOG_ERROR: ftdm_level = FTDM_LOG_LEVEL_ERROR; break;
case WAT_LOG_WARNING: ftdm_level = FTDM_LOG_LEVEL_WARNING; break;
case WAT_LOG_INFO: ftdm_level = FTDM_LOG_LEVEL_INFO; break;
case WAT_LOG_INFO: ftdm_level = FTDM_LOG_LEVEL_INFO; break;
case WAT_LOG_NOTICE: ftdm_level = FTDM_LOG_LEVEL_NOTICE; break;
case WAT_LOG_DEBUG: ftdm_level = FTDM_LOG_LEVEL_DEBUG; break;
case WAT_LOG_DEBUG: ftdm_level = FTDM_LOG_LEVEL_DEBUG; break;
default: ftdm_level = FTDM_LOG_LEVEL_ERROR; break;
};
vsprintf(buff, fmt, argptr);
ftdm_log(FTDM_PRE, ftdm_level, "WAT span %d:%s", span_id, buff);
ftdm_log_chan_ex(gsm_data->dchan, __FILE__, __FUNCTION__, __LINE__, ftdm_level, "%s", buff);
va_end(argptr);
#endif
}
@ -540,7 +519,7 @@ static ftdm_status_t ftdm_gsm_start(ftdm_span_t *span)
{
if (wat_span_start(span->span_id)) {
ftdm_log(FTDM_LOG_ERROR, "Failed to start span %s!\n", span->name);
return FTDM_SUCCESS;
return FTDM_FAIL;
}
return ftdm_thread_create_detached(ftdm_gsm_run, span);
@ -548,13 +527,15 @@ static ftdm_status_t ftdm_gsm_start(ftdm_span_t *span)
static ftdm_status_t ftdm_gsm_stop(ftdm_span_t *span)
{
if (wat_span_stop(span->span_id)) {
ftdm_log(FTDM_LOG_ERROR, "Failed to stop span %s!\n", span->name);
return FTDM_FAIL;
}
return FTDM_SUCCESS;
}
static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_gsm_get_channel_sig_status)
{
ftdm_log(FTDM_LOG_INFO, "\r\nftdm_gsm_get_channel_sig_status\r\n");
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
*status = FTDM_SIG_STATE_UP;
}
@ -698,7 +679,7 @@ static ftdm_state_map_t gsm_state_map = {
static ftdm_status_t ftdm_gsm_state_advance(ftdm_channel_t *ftdmchan)
{
ftdm_log_chan(ftdmchan, STATE_ADVANCE_LOG_LEVEL , "Executing state handler for %s\n", ftdm_channel_state2str(ftdmchan->state));
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Executing state handler for %s\n", ftdm_channel_state2str(ftdmchan->state));
ftdm_channel_complete_state(ftdmchan);
@ -857,6 +838,7 @@ static ftdm_status_t init_wat_lib(void)
wat_interface.wat_sms_ind = on_wat_sms_ind;
wat_interface.wat_sms_sts = on_wat_sms_sts;
wat_interface.wat_span_sts = on_wat_span_status;
wat_interface.wat_dtmf_ind = on_wat_dtmf_ind;
if (wat_register(&wat_interface)) {
ftdm_log(FTDM_LOG_DEBUG, "Failed registering interface to WAT library ...\n");
@ -869,6 +851,30 @@ static ftdm_status_t init_wat_lib(void)
return FTDM_SUCCESS;
}
WAT_AT_CMD_RESPONSE_FUNC(on_dtmf_sent)
{
ftdm_channel_t *ftdmchan = obj;
ftdm_span_t *span = ftdmchan->span;
int i = 0;
if (success == WAT_TRUE) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "DTMF successfully transmitted on span %s\n", span->name);
} else {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Command execution failed on span %s. Err: %s\n", span->name, error);
}
for (i = 0; tokens[i]; i++) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "%s\n", tokens[i]);
}
return i;
}
static ftdm_status_t ftdm_gsm_send_dtmf(ftdm_channel_t *ftdmchan, const char* dtmf)
{
ftdm_gsm_span_data_t *gsm_data = ftdmchan->span->signal_data;
wat_send_dtmf(ftdmchan->span->span_id, gsm_data->call_id, dtmf, on_dtmf_sent, ftdmchan);
return FTDM_SUCCESS;
}
static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling)
{
@ -879,16 +885,22 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling)
ftdm_channel_t *ftdmchan = NULL;
ftdm_channel_t *dchan = NULL;
ftdm_channel_t *bchan = NULL;
ftdm_bool_t hwdtmf_detect = FTDM_FALSE;
ftdm_bool_t hwdtmf_generate = FTDM_FALSE;
unsigned paramindex = 0;
const char *var = NULL;
const char *val = NULL;
int codec = FTDM_CODEC_SLIN;
int interval = 20;
/* libwat is smart enough to set good default values for the timers if they are set to 0 */
memset(&span_config, 0, sizeof(span_config));
/* set some span defaults */
span_config.moduletype = WAT_MODULE_TELIT;
span_config.hardware_dtmf = WAT_FALSE;
if (FTDM_SUCCESS != init_wat_lib()) {
return FTDM_FAIL;
@ -935,10 +947,6 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling)
return FTDM_FAIL;
}
gsm_data = ftdm_calloc(1, sizeof(*gsm_data));
if (!gsm_data) {
return FTDM_FAIL;
@ -946,9 +954,6 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling)
gsm_data->dchan = dchan;
gsm_data->bchan = bchan;
//sprintf(gsm_data->dchan->chan_name, "%s\t\n", "GSM dchan");
//sprintf(gsm_data->bchan->chan_name, "%s\r\n", "GSM bchan");
for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) {
var = ftdm_parameters[paramindex].var;
val = ftdm_parameters[paramindex].val;
@ -966,6 +971,21 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling)
ftdm_log(FTDM_LOG_DEBUG, "Configuring GSM span %s with moduletype %s\n", span->name, val);
} else if (!strcasecmp(var, "debug")) {
span_config.debug_mask = wat_str2debug(val);
ftdm_log(FTDM_LOG_DEBUG, "Configuring GSM span %s with debug mask %s == 0x%X\n", span->name, val, span_config.debug_mask);
} else if (!strcasecmp(var, "hwdtmf")) {
hwdtmf_detect = FTDM_FALSE;
hwdtmf_generate = FTDM_FALSE;
if (!strcasecmp(val, "generate")) {
hwdtmf_generate = FTDM_TRUE;
} else if (!strcasecmp(val, "detect")) {
hwdtmf_detect = FTDM_TRUE;
} else if (!strcasecmp(val, "both") || ftdm_true(val)) {
hwdtmf_detect = FTDM_TRUE;
hwdtmf_generate = FTDM_TRUE;
} else {
span_config.hardware_dtmf = WAT_FALSE;
}
ftdm_log(FTDM_LOG_DEBUG, "Configuring GSM span %s with hardware dtmf %s\n", span->name, val);
} else {
ftdm_log(FTDM_LOG_ERROR, "Ignoring unknown GSM parameter '%s'", var);
}
@ -976,17 +996,24 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling)
span->stop = ftdm_gsm_stop;
span->sig_read = NULL;
span->sig_write = NULL;
if (hwdtmf_detect || hwdtmf_generate) {
span_config.hardware_dtmf = WAT_TRUE;
if (hwdtmf_generate) {
span->sig_send_dtmf = ftdm_gsm_send_dtmf;
}
if (hwdtmf_detect) {
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SIG_DTMF_DETECTION);
}
}
span->signal_cb = sig_cb;
span->signal_type = FTDM_SIGTYPE_GSM;
span->signal_data = gsm_data; /* Gideon, plz fill me with gsm span specific data (you allocate and free) */
span->signal_data = gsm_data;
span->outgoing_call = gsm_outgoing_call;
span->get_span_sig_status = ftdm_gsm_get_span_sig_status;
span->set_span_sig_status = ftdm_gsm_set_span_sig_status;
span->get_channel_sig_status = ftdm_gsm_get_channel_sig_status;
span->set_channel_sig_status = ftdm_gsm_set_channel_sig_status;
//printf("\r\nspan->state_map = &gsm_state_map;\r\n");
span->state_map = &gsm_state_map;
span->state_processor = ftdm_gsm_state_advance;
@ -999,28 +1026,14 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling)
gsm_data->span = span;
#if 0
/* setup the scheduler (create if needed) */
snprintf(schedname, sizeof(schedname), "ftmod_r2_%s", span->name);
ftdm_assert(ftdm_sched_create(&r2data->sched, schedname) == FTDM_SUCCESS, "Failed to create schedule!\n");
spanpvt->sched = r2data->sched;
#endif
fprintf(stdout, "Configuring wat span %d %s \r\n", span->span_id, span->name);
if (wat_span_config(span->span_id, &span_config)) {
ftdm_log(FTDM_LOG_ERROR, "Failed to configure span %s for GSM signaling!!\n", span->name);
return FTDM_FAIL;
}
{
int codec = FTDM_CODEC_SLIN;
int interval = 20;
ftdm_channel_command(gsm_data->bchan, FTDM_COMMAND_SET_NATIVE_CODEC, &codec);
ftdm_channel_command(gsm_data->bchan, FTDM_COMMAND_SET_CODEC, &codec);
ftdm_channel_command(gsm_data->bchan, FTDM_COMMAND_SET_INTERVAL, &interval);
}
ftdm_channel_command(gsm_data->bchan, FTDM_COMMAND_SET_NATIVE_CODEC, &codec);
ftdm_channel_command(gsm_data->bchan, FTDM_COMMAND_SET_CODEC, &codec);
ftdm_channel_command(gsm_data->bchan, FTDM_COMMAND_SET_INTERVAL, &interval);
return FTDM_SUCCESS;

View File

@ -1304,7 +1304,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
span->indicate = ftdm_sangoma_isdn_indicate;
span->channel_request = NULL;
span->signal_cb = sig_cb;
span->sig_dtmf = ftdm_sangoma_isdn_dtmf;
span->sig_queue_dtmf = ftdm_sangoma_isdn_dtmf;
span->get_channel_sig_status = ftdm_sangoma_isdn_get_chan_sig_status;
span->set_channel_sig_status = ftdm_sangoma_isdn_set_chan_sig_status;
span->get_span_sig_status = ftdm_sangoma_isdn_get_span_sig_status;

View File

@ -513,7 +513,8 @@ struct ftdm_span {
ftdm_span_stop_t stop;
ftdm_channel_sig_read_t sig_read;
ftdm_channel_sig_write_t sig_write;
ftdm_channel_sig_dtmf_t sig_dtmf;
ftdm_channel_sig_dtmf_t sig_queue_dtmf;
ftdm_channel_sig_dtmf_t sig_send_dtmf;
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

@ -92,6 +92,9 @@ FT_DECLARE(ftdm_status_t) ftdm_sched_get_time_to_next_timer(const ftdm_sched_t *
/*! \brief Global initialization, called just once, this is called by FreeTDM core, other users MUST not call it */
FT_DECLARE(ftdm_status_t) ftdm_sched_global_init(void);
/*! \brief Global destroy, called just once, this is called by FreeTDM core, other users MUST not call it */
FT_DECLARE(ftdm_status_t) ftdm_sched_global_destroy(void);
/*! \brief Checks if the main scheduling thread is running */
FT_DECLARE(ftdm_bool_t) ftdm_free_sched_running(void);

View File

@ -268,9 +268,11 @@ typedef enum {
#define FTDM_CHANNEL_DIGITAL_MEDIA (1ULL << 36)
/*!< Native signaling bridge is enabled */
#define FTDM_CHANNEL_NATIVE_SIGBRIDGE (1ULL << 37)
/*!< Native signaling DTMF detection */
#define FTDM_CHANNEL_SIG_DTMF_DETECTION (1ULL << 38)
/*!< This no more flags after this flag */
#define FTDM_CHANNEL_MAX_FLAG (1ULL << 38)
#define FTDM_CHANNEL_MAX_FLAG (1ULL << 39)
/*!<When adding a new flag, need to update ftdm_io.c:channel_flag_strs */
#include "ftdm_state.h"

View File

@ -1 +1 @@
Thu May 22 15:39:33 UTC 2014
Sat Jul 12 04:39:49 CDT 2014

View File

@ -350,8 +350,15 @@ int su_getsocktype(su_socket_t s)
int su_setreuseaddr(su_socket_t s, int reuse)
{
return setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
(void *)&reuse, (socklen_t)sizeof(reuse));
#ifdef SO_REUSEPORT
if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT,
(void *)&reuse, (socklen_t)sizeof(reuse)) < 0)
return -1;
#endif
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
(void *)&reuse, (socklen_t)sizeof(reuse)) < 0)
return -1;
return 0;
}

View File

@ -217,7 +217,7 @@ int tport_recv_stream_ws(tport_t *self)
N = ws_read_frame(&wstp->ws, &oc, &data);
if (N == -2) {
return 2;
return 1;
}
if ((N == -1000) || (N == 0)) {

View File

@ -368,18 +368,25 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block)
ssize_t ws_raw_write(wsh_t *wsh, void *data, size_t bytes)
{
size_t r;
int sanity = 2000;
if (wsh->ssl) {
do {
r = SSL_write(wsh->ssl, data, bytes);
} while (r == -1 && SSL_get_error(wsh->ssl, r) == SSL_ERROR_WANT_WRITE);
if (sanity < 2000) {
ms_sleep(1);
}
} while (--sanity > 0 && r == -1 && SSL_get_error(wsh->ssl, r) == SSL_ERROR_WANT_WRITE);
return r;
}
do {
r = send(wsh->sock, data, bytes, 0);
} while (r == -1 && xp_is_blocking(xp_errno()));
if (sanity < 2000) {
ms_sleep(1);
}
} while (--sanity > 0 && r == -1 && xp_is_blocking(xp_errno()));
//if (r<0) {
//printf("wRITE FAIL: %s\n", strerror(errno));

View File

@ -1 +1 @@
Tue Dec 6 17:55:59 CST 2011
Thu Jun 5 22:07:01 CDT 2014

View File

@ -41,6 +41,11 @@
#define GEN_CONST
#include <math.h>
#endif
#if defined(HAVE_STDBOOL_H)
#include <stdbool.h>
#else
#include "spandsp/stdbool.h"
#endif
#include "floating_fudge.h"
#include "spandsp.h"
@ -48,9 +53,6 @@
#define PACKET_LOSS_TIME -1
#define FALSE 0
#define TRUE (!FALSE)
g1050_constants_t g1050_constants[1] =
{
{
@ -746,7 +748,7 @@ static void g1050_segment_init(g1050_segment_state_t *s,
s->max_jitter = parms->max_jitter;
/* The following is common state information to all links. */
s->high_loss = FALSE;
s->high_loss = false;
s->congestion_delay = 0.0;
s->last_arrival_time = 0.0;
@ -797,7 +799,7 @@ static void g1050_core_init(g1050_core_state_t *s, g1050_core_model_t *parms, in
static void g1050_segment_model(g1050_segment_state_t *s, double delays[], int len)
{
int i;
int lose;
bool lose;
int was_high_loss;
double impulse;
double slice_delay;
@ -805,7 +807,7 @@ static void g1050_segment_model(g1050_segment_state_t *s, double delays[], int l
/* Compute delay and loss value for each time slice. */
for (i = 0; i < len; i++)
{
lose = FALSE;
lose = false;
/* Initialize delay to the serial delay plus some jitter. */
slice_delay = s->serial_delay + s->max_jitter*q1050_rand();
/* If no QoS, do congestion delay and packet loss analysis. */
@ -826,14 +828,14 @@ static void g1050_segment_model(g1050_segment_state_t *s, double delays[], int l
}
if (was_high_loss && q1050_rand() < s->prob_packet_loss)
lose = TRUE;
lose = true;
/* Single pole LPF for the congestion delay impulses. */
s->congestion_delay = s->congestion_delay*s->impulse_coeff + impulse*(1.0 - s->impulse_coeff);
slice_delay += s->congestion_delay;
}
/* If duplex mismatch on LAN, packet loss based on loss probability. */
if (s->multiple_access && (q1050_rand() < s->prob_packet_collision_loss))
lose = TRUE;
lose = true;
/* Put computed delay into time slice array. */
if (lose)
{
@ -851,12 +853,12 @@ static void g1050_segment_model(g1050_segment_state_t *s, double delays[], int l
static void g1050_core_model(g1050_core_state_t *s, double delays[], int len)
{
int32_t i;
int lose;
bool lose;
double jitter_delay;
for (i = 0; i < len; i++)
{
lose = FALSE;
lose = false;
jitter_delay = s->base_delay + s->max_jitter*q1050_rand();
/* Route flapping */
if (--s->route_flap_counter <= 0)
@ -866,18 +868,18 @@ static void g1050_core_model(g1050_core_state_t *s, double delays[], int len)
s->route_flap_counter = s->route_flap_interval;
}
if (q1050_rand() < s->prob_packet_loss)
lose = TRUE;
lose = true;
/* Link failures */
if (--s->link_failure_counter <= 0)
{
/* We are in a link failure */
lose = TRUE;
lose = true;
if (--s->link_recovery_counter <= 0)
{
/* Leave failure state. */
s->link_failure_counter = s->link_failure_interval_ticks;
s->link_recovery_counter = s->link_failure_duration_ticks;
lose = FALSE;
lose = false;
}
}
if (lose)
@ -1056,23 +1058,23 @@ static void g1050_simulate_chunk(g1050_state_t *s)
s->base_time += 1.0;
memcpy(&s->segment[0].delays[0], &s->segment[0].delays[G1050_TICKS_PER_SEC], 2*G1050_TICKS_PER_SEC*sizeof(s->segment[0].delays[0]));
memmove(&s->segment[0].delays[0], &s->segment[0].delays[G1050_TICKS_PER_SEC], 2*G1050_TICKS_PER_SEC*sizeof(s->segment[0].delays[0]));
g1050_segment_model(&s->segment[0], &s->segment[0].delays[2*G1050_TICKS_PER_SEC], G1050_TICKS_PER_SEC);
memcpy(&s->segment[1].delays[0], &s->segment[1].delays[G1050_TICKS_PER_SEC], 2*G1050_TICKS_PER_SEC*sizeof(s->segment[1].delays[0]));
memmove(&s->segment[1].delays[0], &s->segment[1].delays[G1050_TICKS_PER_SEC], 2*G1050_TICKS_PER_SEC*sizeof(s->segment[1].delays[0]));
g1050_segment_model(&s->segment[1], &s->segment[1].delays[2*G1050_TICKS_PER_SEC], G1050_TICKS_PER_SEC);
memcpy(&s->core.delays[0], &s->core.delays[G1050_TICKS_PER_SEC], 2*G1050_TICKS_PER_SEC*sizeof(s->core.delays[0]));
memmove(&s->core.delays[0], &s->core.delays[G1050_TICKS_PER_SEC], 2*G1050_TICKS_PER_SEC*sizeof(s->core.delays[0]));
g1050_core_model(&s->core, &s->core.delays[2*G1050_TICKS_PER_SEC], G1050_TICKS_PER_SEC);
memcpy(&s->segment[2].delays[0], &s->segment[2].delays[G1050_TICKS_PER_SEC], 2*G1050_TICKS_PER_SEC*sizeof(s->segment[2].delays[0]));
memmove(&s->segment[2].delays[0], &s->segment[2].delays[G1050_TICKS_PER_SEC], 2*G1050_TICKS_PER_SEC*sizeof(s->segment[2].delays[0]));
g1050_segment_model(&s->segment[2], &s->segment[2].delays[2*G1050_TICKS_PER_SEC], G1050_TICKS_PER_SEC);
memcpy(&s->segment[3].delays[0], &s->segment[3].delays[G1050_TICKS_PER_SEC], 2*G1050_TICKS_PER_SEC*sizeof(s->segment[3].delays[0]));
memmove(&s->segment[3].delays[0], &s->segment[3].delays[G1050_TICKS_PER_SEC], 2*G1050_TICKS_PER_SEC*sizeof(s->segment[3].delays[0]));
g1050_segment_model(&s->segment[3], &s->segment[3].delays[2*G1050_TICKS_PER_SEC], G1050_TICKS_PER_SEC);
memcpy(&s->arrival_times_1[0], &s->arrival_times_1[s->packet_rate], 2*s->packet_rate*sizeof(s->arrival_times_1[0]));
memcpy(&s->arrival_times_2[0], &s->arrival_times_2[s->packet_rate], 2*s->packet_rate*sizeof(s->arrival_times_2[0]));
memmove(&s->arrival_times_1[0], &s->arrival_times_1[s->packet_rate], 2*s->packet_rate*sizeof(s->arrival_times_1[0]));
memmove(&s->arrival_times_2[0], &s->arrival_times_2[s->packet_rate], 2*s->packet_rate*sizeof(s->arrival_times_2[0]));
for (i = 0; i < s->packet_rate; i++)
{
s->arrival_times_1[2*s->packet_rate + i] = s->base_time + 2.0 + (double) i/(double) s->packet_rate;
@ -1126,7 +1128,7 @@ SPAN_DECLARE(g1050_state_t *) g1050_init(int model,
&mo->sidea_lan,
sp->sidea_lan_bit_rate,
sp->sidea_lan_multiple_access,
FALSE,
false,
packet_size,
packet_rate);
g1050_segment_init(&s->segment[1],
@ -1134,7 +1136,7 @@ SPAN_DECLARE(g1050_state_t *) g1050_init(int model,
&constants->segment[1],
&mo->sidea_access_link,
sp->sidea_access_link_bit_rate_ab,
FALSE,
false,
sp->sidea_access_link_qos_enabled,
packet_size,
packet_rate);
@ -1144,7 +1146,7 @@ SPAN_DECLARE(g1050_state_t *) g1050_init(int model,
&constants->segment[2],
&mo->sideb_access_link,
sp->sideb_access_link_bit_rate_ba,
FALSE,
false,
sp->sideb_access_link_qos_enabled,
packet_size,
packet_rate);
@ -1154,7 +1156,7 @@ SPAN_DECLARE(g1050_state_t *) g1050_init(int model,
&mo->sideb_lan,
sp->sideb_lan_bit_rate,
sp->sideb_lan_multiple_access,
FALSE,
false,
packet_size,
packet_rate);
@ -1186,6 +1188,13 @@ SPAN_DECLARE(g1050_state_t *) g1050_init(int model,
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) g1050_free(g1050_state_t *s)
{
free(s);
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) g1050_dump_parms(int model, int speed_pattern)
{
g1050_channel_speeds_t *sp;

View File

@ -41,6 +41,11 @@
#define GEN_CONST
#include <math.h>
#endif
#if defined(HAVE_STDBOOL_H)
#include <stdbool.h>
#else
#include "spandsp/stdbool.h"
#endif
#include "floating_fudge.h"
#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
@ -345,7 +350,7 @@ SPAN_DECLARE(void) one_way_line_model_set_mains_pickup(one_way_line_model_state_
if (f)
{
tone_gen_descriptor_init(&mains_tone_desc, f, (int) (level - 10.0f), f*3, (int) level, 1, 0, 0, 0, TRUE);
tone_gen_descriptor_init(&mains_tone_desc, f, (int) (level - 10.0f), f*3, (int) level, 1, 0, 0, 0, true);
tone_gen_init(&s->mains_tone, &mains_tone_desc);
}
s->mains_interference = f;
@ -454,9 +459,9 @@ SPAN_DECLARE(void) both_ways_line_model_set_mains_pickup(both_ways_line_model_st
if (f)
{
tone_gen_descriptor_init(&mains_tone_desc, f, (int) (level1 - 10.0f), f*3, (int) level1, 1, 0, 0, 0, TRUE);
tone_gen_descriptor_init(&mains_tone_desc, f, (int) (level1 - 10.0f), f*3, (int) level1, 1, 0, 0, 0, true);
tone_gen_init(&s->line1.mains_tone, &mains_tone_desc);
tone_gen_descriptor_init(&mains_tone_desc, f, (int) (level2 - 10.0f), f*3, (int) level2, 1, 0, 0, 0, TRUE);
tone_gen_descriptor_init(&mains_tone_desc, f, (int) (level2 - 10.0f), f*3, (int) level2, 1, 0, 0, 0, true);
tone_gen_init(&s->line2.mains_tone, &mains_tone_desc);
}
s->line1.mains_interference = f;
@ -494,8 +499,9 @@ SPAN_DECLARE(one_way_line_model_state_t *) one_way_line_model_init(int model, fl
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) one_way_line_model_release(one_way_line_model_state_t *s)
SPAN_DECLARE(int) one_way_line_model_free(one_way_line_model_state_t *s)
{
codec_munge_free(s->munge);
free(s);
return 0;
}
@ -559,8 +565,10 @@ SPAN_DECLARE(both_ways_line_model_state_t *) both_ways_line_model_init(int model
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) both_ways_line_model_release(both_ways_line_model_state_t *s)
SPAN_DECLARE(int) both_ways_line_model_free(both_ways_line_model_state_t *s)
{
codec_munge_free(s->line1.munge);
codec_munge_free(s->line2.munge);
free(s);
return 0;
}

View File

@ -40,17 +40,16 @@
#include <inttypes.h>
#include <string.h>
#include <stdio.h>
#include "floating_fudge.h"
#if defined(HAVE_FFTW3_H)
#include <fftw3.h>
#else
#include <fftw.h>
#endif
#if defined(HAVE_TGMATH_H)
#include <tgmath.h>
#endif
#if defined(HAVE_MATH_H)
#include <math.h>
#if defined(HAVE_STDBOOL_H)
#include <stdbool.h>
#else
#include "spandsp/stdbool.h"
#endif
#include "spandsp.h"

View File

@ -41,6 +41,11 @@
#define GEN_CONST
#include <math.h>
#endif
#if defined(HAVE_STDBOOL_H)
#include <stdbool.h>
#else
#include "spandsp/stdbool.h"
#endif
#include "floating_fudge.h"
#include "spandsp.h"
@ -49,9 +54,6 @@
#define PACKET_LOSS_TIME -1
#define FALSE 0
#define TRUE (!FALSE)
SPAN_DECLARE(rfc2198_sim_state_t *) rfc2198_sim_init(int model,
int speed_pattern,
int packet_size,
@ -70,6 +72,14 @@ SPAN_DECLARE(rfc2198_sim_state_t *) rfc2198_sim_init(int model,
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) rfc2198_sim_free(rfc2198_sim_state_t *s)
{
g1050_free(s->g1050);
free(s);
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) rfc2198_sim_put(rfc2198_sim_state_t *s,
const uint8_t buf[],
int len,

View File

@ -272,6 +272,8 @@ SPAN_DECLARE(g1050_state_t *) g1050_init(int model,
int packet_size,
int packet_rate);
SPAN_DECLARE(int) g1050_free(g1050_state_t *s);
SPAN_DECLARE(void) g1050_dump_parms(int model, int speed_pattern);
SPAN_DECLARE(int) g1050_put(g1050_state_t *s,

View File

@ -154,7 +154,7 @@ SPAN_DECLARE(both_ways_line_model_state_t *) both_ways_line_model_init(int model
int codec,
int rbs_pattern);
SPAN_DECLARE(int) both_ways_line_model_release(both_ways_line_model_state_t *s);
SPAN_DECLARE(int) both_ways_line_model_free(both_ways_line_model_state_t *s);
SPAN_DECLARE(void) one_way_line_model(one_way_line_model_state_t *s,
int16_t output[],
@ -167,7 +167,7 @@ SPAN_DECLARE(void) one_way_line_model_set_mains_pickup(one_way_line_model_state_
SPAN_DECLARE(one_way_line_model_state_t *) one_way_line_model_init(int model, float noise, int codec, int rbs_pattern);
SPAN_DECLARE(int) one_way_line_model_release(one_way_line_model_state_t *s);
SPAN_DECLARE(int) one_way_line_model_free(one_way_line_model_state_t *s);
#ifdef __cplusplus
}

View File

@ -73,6 +73,8 @@ SPAN_DECLARE(rfc2198_sim_state_t *) rfc2198_sim_init(int model,
int packet_rate,
int redundancy_depth);
SPAN_DECLARE(int) rfc2198_sim_free(rfc2198_sim_state_t *s);
SPAN_DECLARE(int) rfc2198_sim_put(rfc2198_sim_state_t *s,
const uint8_t buf[],
int len,

View File

@ -51,7 +51,7 @@ extern "C" {
SPAN_DECLARE(complexify_state_t *) complexify_init(void);
SPAN_DECLARE(void) complexify_release(complexify_state_t *s);
SPAN_DECLARE(int) complexify_free(complexify_state_t *s);
SPAN_DECLARE(complexf_t) complexify(complexify_state_t *s, int16_t amp);
@ -61,7 +61,7 @@ SPAN_DECLARE(void) ifft(complex_t data[], int len);
SPAN_DECLARE(codec_munge_state_t *) codec_munge_init(int codec, int info);
SPAN_DECLARE(void) codec_munge_release(codec_munge_state_t *s);
SPAN_DECLARE(void) codec_munge_free(codec_munge_state_t *s);
SPAN_DECLARE(void) codec_munge(codec_munge_state_t *s, int16_t amp[], int len);

View File

@ -39,6 +39,11 @@
#if defined(HAVE_MATH_H)
#include <math.h>
#endif
#if defined(HAVE_STDBOOL_H)
#include <stdbool.h>
#else
#include "spandsp/stdbool.h"
#endif
#include "floating_fudge.h"
#include <time.h>
#include <fcntl.h>
@ -66,12 +71,14 @@ struct complexify_state_s
};
static complex_t circle[MAX_FFT_LEN/2];
static int circle_init = FALSE;
static int circle_init = false;
static complex_t icircle[MAX_FFT_LEN/2];
static int icircle_init = FALSE;
static int icircle_init = false;
#define SF_MAX_HANDLE 32
static int sf_close_at_exit_registered = FALSE;
static int sf_close_at_exit_registered = false;
static SNDFILE *sf_close_at_exit_list[SF_MAX_HANDLE] =
{
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@ -95,9 +102,10 @@ SPAN_DECLARE(complexify_state_t *) complexify_init(void)
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) complexify_release(complexify_state_t *s)
SPAN_DECLARE(int) complexify_free(complexify_state_t *s)
{
free(s);
return 0;
}
/*- End of function --------------------------------------------------------*/
@ -243,7 +251,7 @@ SPAN_DECLARE(void) fft(complex_t data[], int len)
x = -(2.0*3.1415926535*i)/(double) MAX_FFT_LEN;
circle[i] = expj(x);
}
circle_init = TRUE;
circle_init = true;
}
fftx(data, temp, len);
}
@ -263,7 +271,7 @@ SPAN_DECLARE(void) ifft(complex_t data[], int len)
x = (2.0*3.1415926535*i)/(double) MAX_FFT_LEN;
icircle[i] = expj(x);
}
icircle_init = TRUE;
icircle_init = true;
}
ifftx(data, temp, len);
}
@ -308,7 +316,7 @@ SPAN_DECLARE(codec_munge_state_t *) codec_munge_init(int codec, int info)
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) codec_munge_release(codec_munge_state_t *s)
SPAN_DECLARE(void) codec_munge_free(codec_munge_state_t *s)
{
free(s);
}
@ -389,7 +397,7 @@ static int sf_record_handle(SNDFILE *handle)
if (!sf_close_at_exit_registered)
{
atexit(sf_close_at_exit);
sf_close_at_exit_registered = TRUE;
sf_close_at_exit_registered = true;
}
return 0;
}
@ -455,7 +463,6 @@ SPAN_DECLARE(int) sf_close_telephony(SNDFILE *handle)
{
if (sf_close_at_exit_list[i] == handle)
{
sf_close(sf_close_at_exit_list[i]);
sf_close_at_exit_list[i] = NULL;
break;
}

View File

@ -33,6 +33,7 @@
modem CDATA #IMPLIED
tag CDATA #IMPLIED
value CDATA #IMPLIED
timein CDATA #IMPLIED
timeout CDATA #IMPLIED
crc_error CDATA #IMPLIED
pattern CDATA #IMPLIED

View File

@ -91,6 +91,9 @@
<step dir="T" type="PREAMBLE" modem="V.21"/>
<step dir="T" type="HDLC" tag="DCN" value="FF C8 5F"/>
<step dir="T" type="POSTAMBLE"/>
<step dir="T" type="CLEAR"/>
<step dir="R" type="CLEAR" timein="0" timeout="100"/>
<step type="STATUS" value="RX_DCNDATA"/>
</test>
<test name="V17-12000-V29-9600">
<!-- Tester calls, trying to provoke a crash seen in some versions of spandsp, when
@ -183,6 +186,198 @@
<step dir="T" type="PREAMBLE" modem="V.21"/>
<step dir="T" type="HDLC" tag="DCN" value="FF C8 5F"/>
<step dir="T" type="POSTAMBLE"/>
<step dir="T" type="CLEAR"/>
<step dir="R" type="CLEAR" timein="0" timeout="100"/>
<step type="STATUS" value="OK"/>
</test>
<test name="Phase-D-collision">
<!-- DUT calls tester and sends 1 IMPRESS and 1 WHITE page. The MCF after the first
page is delayed enough to cause a collision with a retry of the MPS from the DUT. -->
<step type="ANSWER" value="etsi_300_242_a4_impress_white.tif"/>
<step dir="T" type="SET" tag="IDENT" value="+0123456789"/>
<step dir="R" type="CNG"/>
<step dir="T" type="CED"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.21"/>
<step dir="T" type="HDLC" tag="DIS" value="FF C8 01 00 50 00"/>
<step dir="T" type="POSTAMBLE"/>
<step dir="R" type="HDLC" modem="V.21" tag="TSI+" value="FF C0 C2 9C 1C EC 6C AC 2C CC 4C 8C 0C D4 04 04 04 04 04 04 04 04 04 ..."/>
<step dir="R" type="HDLC" tag="DCS+" value="FF C8 C1 ..."/>
<step dir="R" type="TCF" modem="V.27ter/4800" timeout="60000"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.21"/>
<step dir="T" type="HDLC" tag="CFR" value="FF C8 21"/>
<step dir="T" type="POSTAMBLE"/>
<step dir="R" type="MSG" modem="V.27ter/4800" timeout="180000"/>
<step dir="R" type="HDLC" modem="V.21" tag="MPS+" value="FF C8 F2"/>
<step type="WAIT" value="3500"/>
<step dir="T" type="PREAMBLE" modem="V.21"/>
<step dir="T" type="HDLC" tag="MCF" value="FF C8 31"/>
<step dir="T" type="POSTAMBLE"/>
<step dir="R" type="MSG" modem="V.27ter/4800" timeout="60000"/>
<step dir="R" type="HDLC" modem="V.21" tag="EOP+" value="FF C8 F4"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.21"/>
<step dir="T" type="HDLC" tag="MCF" value="FF C8 31"/>
<step dir="T" type="POSTAMBLE"/>
<step dir="R" type="HDLC" modem="V.21" tag="DCN+" value="FF C8 DF"/>
<step dir="R" type="CLEAR" timein="800" timeout="1200"/>
<step type="STATUS" value="OK"/>
</test>
<test name="Modem-change-at-CTC">
<!-- Similar test to TSB85/OREN03, but there is a modem change at the CTC -->
<!-- Tester calls DUT and sends one 15k byte STAIRSTEP page. -->
<step type="CALL"/>
<!--<step dir="T" type="CNG"/>-->
<step dir="R" type="CED"/>
<step dir="R" type="HDLC" modem="V.21" tag="DIS" value="FF C8 01 ..." timeout="60000"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.21"/>
<step dir="T" type="HDLC" tag="DCS" value="FF C8 41 00 60 1F 20"/>
<step dir="T" type="POSTAMBLE"/>
<step type="WAIT" value="75"/>
<step dir="T" type="TCF" modem="V.29/9600" value="1800"/>
<step dir="R" type="HDLC" modem="V.21" tag="CFR" value="FF C8 21"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.29/9600"/>
<step dir="T" type="PP" value="etsi_300_242_a4_stairstep.tif" frame_size="64" crc_error="0"/>
<step dir="T" type="POSTAMBLE"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.21"/>
<step dir="T" type="HDLC" tag="PPS-EOP" value="FF C8 7D 74 00 00 10"/>
<step dir="T" type="POSTAMBLE"/>
<possible-step>
<step dir="R" type="HDLC" modem="V.21" tag="RNR" value="FF C8 37"/>
<step dir="R" type="SILENCE"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.21"/>
<step dir="T" type="HDLC" tag="RR" value="FF C8 76"/>
<step dir="T" type="POSTAMBLE"/>
</possible-step>
<step dir="R" type="HDLC" modem="V.21" tag="PPR" value="FF C8 3D 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 FF FF FF FF FF"/>
<step dir="R" type="SILENCE"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.29/9600"/>
<step dir="T" type="PP" value="etsi_300_242_a4_stairstep.tif" frame_size="64" crc_error="0"/>
<step dir="T" type="POSTAMBLE"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.21"/>
<step dir="T" type="HDLC" tag="PPS-EOP" value="FF C8 7D 74 00 00 10"/>
<step dir="T" type="POSTAMBLE"/>
<possible-step>
<step dir="R" type="HDLC" modem="V.21" tag="RNR" value="FF C8 37"/>
<step dir="R" type="SILENCE"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.21"/>
<step dir="T" type="HDLC" tag="RR" value="FF C8 76"/>
<step dir="T" type="POSTAMBLE"/>
</possible-step>
<step dir="R" type="HDLC" modem="V.21" tag="PPR" value="FF C8 3D 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 FF FF FF FF FF"/>
<step dir="R" type="SILENCE"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.29/9600"/>
<step dir="T" type="PP" value="etsi_300_242_a4_stairstep.tif" frame_size="64" crc_error="0"/>
<step dir="T" type="POSTAMBLE"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.21"/>
<step dir="T" type="HDLC" tag="PPS-EOP" value="FF C8 7D 74 00 00 10"/>
<step dir="T" type="POSTAMBLE"/>
<possible-step>
<step dir="R" type="HDLC" modem="V.21" tag="RNR" value="FF C8 37"/>
<step dir="R" type="SILENCE"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.21"/>
<step dir="T" type="HDLC" tag="RR" value="FF C8 76"/>
<step dir="T" type="POSTAMBLE"/>
</possible-step>
<step dir="R" type="HDLC" modem="V.21" tag="PPR" value="FF C8 3D 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 FF FF FF FF FF"/>
<step dir="R" type="SILENCE"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.29/9600"/>
<step dir="T" type="PP" value="etsi_300_242_a4_stairstep.tif" frame_size="64" crc_error="0"/>
<step dir="T" type="POSTAMBLE"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.21"/>
<step dir="T" type="HDLC" tag="PPS-EOP" value="FF C8 7D 74 00 00 10"/>
<step dir="T" type="POSTAMBLE"/>
<possible-step>
<step dir="R" type="HDLC" modem="V.21" tag="RNR" value="FF C8 37"/>
<step dir="R" type="SILENCE"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.21"/>
<step dir="T" type="HDLC" tag="RR" value="FF C8 76"/>
<step dir="T" type="POSTAMBLE"/>
</possible-step>
<step dir="R" type="HDLC" modem="V.21" tag="PPR" value="FF C8 3D 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 FF FF FF FF FF"/>
<step dir="R" type="SILENCE"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.21"/>
<step dir="T" type="HDLC" tag="CTC + V.27ter/4800" value="FF C8 48 00 10"/>
<step dir="T" type="POSTAMBLE"/>
<step dir="R" type="HDLC" modem="V.21" tag="CTR" value="FF C8 23"/>
<step dir="R" type="SILENCE"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.27ter/4800"/>
<step dir="T" type="PP" value="etsi_300_242_a4_stairstep.tif" frame_size="64"/>
<step dir="T" type="POSTAMBLE"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.21"/>
<step dir="T" type="HDLC" tag="PPS-EOP" value="FF C8 7D 74 00 00 6B"/>
<step dir="T" type="POSTAMBLE"/>
<possible-step>
<step dir="R" type="HDLC" modem="V.21" tag="RNR" value="FF C8 37"/>
<step dir="R" type="SILENCE"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.21"/>
<step dir="T" type="HDLC" tag="RR" value="FF C8 76"/>
<step dir="T" type="POSTAMBLE"/>
</possible-step>
<step dir="R" type="HDLC" modem="V.21" tag="MCF" value="FF C8 31"/>
<step dir="R" type="SILENCE"/>
<step type="WAIT" value="75"/>
<step dir="T" type="PREAMBLE" modem="V.21"/>
<step dir="T" type="HDLC" tag="DCN" value="FF C8 5F"/>
<step dir="T" type="POSTAMBLE"/>
<step dir="T" type="CLEAR"/>
<step dir="R" type="CLEAR" timein="0" timeout="100"/>
<step type="STATUS" value="OK"/>
</test>
</test-group>
</fax-tests>

File diff suppressed because it is too large Load Diff

View File

@ -1029,13 +1029,13 @@ SPAN_DECLARE(int) adsi_add_field(adsi_tx_state_t *s, uint8_t *msg, int len, uint
msg[len++] = (uint8_t) field_len;
if (field_len == DLE)
msg[len++] = (uint8_t) field_len;
memcpy(msg + len, field_body, field_len);
memcpy(&msg[len], field_body, field_len);
len += field_len;
}
else
{
/* No field type or length, for restricted single message formats */
memcpy(msg + len, field_body, field_len);
memcpy(&msg[len], field_body, field_len);
len += field_len;
}
}
@ -1080,7 +1080,7 @@ SPAN_DECLARE(int) adsi_add_field(adsi_tx_state_t *s, uint8_t *msg, int len, uint
x = msg[--len];
if (field_type != CLIP_DTMF_HASH_UNSPECIFIED)
msg[len++] = field_type;
memcpy(msg + len, field_body, field_len);
memcpy(&msg[len], field_body, field_len);
msg[len + field_len] = (uint8_t) x;
len += (field_len + 1);
}

View File

@ -5411,7 +5411,7 @@ static int command_search(const char *u, int *matched)
entry = 0;
/* Loop over the length of the string to search the trie... */
for (i = 0, ptr = 0; ptr < COMMAND_TRIE_LEN; i++)
for (i = 0, ptr = 0; ptr < COMMAND_TRIE_LEN - 2; i++)
{
/* The character in u we are processing... */
/* V.250 5.4.1 says upper and lower case are equivalent in commands */

View File

@ -348,12 +348,14 @@ SPAN_DECLARE(bell_mf_tx_state_t *) bell_mf_tx_init(bell_mf_tx_state_t *s)
SPAN_DECLARE(int) bell_mf_tx_release(bell_mf_tx_state_t *s)
{
queue_release(&s->queue.queue);
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) bell_mf_tx_free(bell_mf_tx_state_t *s)
{
queue_release(&s->queue.queue);
span_free(s);
return 0;
}

View File

@ -597,12 +597,14 @@ SPAN_DECLARE(dtmf_tx_state_t *) dtmf_tx_init(dtmf_tx_state_t *s,
SPAN_DECLARE(int) dtmf_tx_release(dtmf_tx_state_t *s)
{
queue_release(&s->queue.queue);
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) dtmf_tx_free(dtmf_tx_state_t *s)
{
queue_release(&s->queue.queue);
span_free(s);
return 0;
}

View File

@ -394,7 +394,7 @@ SPAN_DECLARE(logging_state_t *) fax_get_logging_state(fax_state_t *s)
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) fax_restart(fax_state_t *s, int calling_party)
SPAN_DECLARE(int) fax_restart(fax_state_t *s, bool calling_party)
{
v8_parms_t v8_parms;
@ -420,7 +420,7 @@ SPAN_DECLARE(int) fax_restart(fax_state_t *s, int calling_party)
v8_parms.nsf = -1;
v8_parms.t66 = -1;
v8_restart(&s->v8, calling_party, &v8_parms);
t30_restart(&s->t30);
t30_restart(&s->t30, calling_party);
#if defined(LOG_FAX_AUDIO)
{
char buf[100 + 1];
@ -455,7 +455,7 @@ SPAN_DECLARE(int) fax_restart(fax_state_t *s, int calling_party)
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(fax_state_t *) fax_init(fax_state_t *s, int calling_party)
SPAN_DECLARE(fax_state_t *) fax_init(fax_state_t *s, bool calling_party)
{
v8_parms_t v8_parms;
@ -515,13 +515,14 @@ SPAN_DECLARE(fax_state_t *) fax_init(fax_state_t *s, int calling_party)
SPAN_DECLARE(int) fax_release(fax_state_t *s)
{
t30_release(&s->t30);
v8_release(&s->v8);
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) fax_free(fax_state_t *s)
{
t30_release(&s->t30);
fax_release(s);
span_free(s);
return 0;
}

View File

@ -172,7 +172,10 @@ SPAN_DECLARE_NONSTD(void) fax_modems_hdlc_tx_frame(void *user_data, const uint8_
s = (fax_modems_state_t *) user_data;
hdlc_tx_frame(&s->hdlc_tx, msg, len);
if (len == -1)
hdlc_tx_restart(&s->hdlc_tx);
else
hdlc_tx_frame(&s->hdlc_tx, msg, len);
}
/*- End of function --------------------------------------------------------*/

View File

@ -311,6 +311,20 @@ SPAN_DECLARE(void) hdlc_rx_set_octet_counting_report_interval(hdlc_rx_state_t *s
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) hdlc_rx_restart(hdlc_rx_state_t *s)
{
s->framing_ok_announced = false;
s->flags_seen = 0;
s->raw_bit_stream = 0;
s->byte_in_progress = 0;
s->num_bits = 0;
s->octet_counting_mode = false;
s->octet_count = 0;
s->len = 0;
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(hdlc_rx_state_t *) hdlc_rx_init(hdlc_rx_state_t *s,
bool crc32,
bool report_bad_frames,
@ -375,7 +389,7 @@ SPAN_DECLARE(int) hdlc_rx_get_stats(hdlc_rx_state_t *s,
SPAN_DECLARE(int) hdlc_tx_frame(hdlc_tx_state_t *s, const uint8_t *frame, size_t len)
{
if (len <= 0)
if (len == 0)
{
s->tx_end = true;
return 0;
@ -394,7 +408,7 @@ SPAN_DECLARE(int) hdlc_tx_frame(hdlc_tx_state_t *s, const uint8_t *frame, size_t
if (s->len)
return -1;
}
memcpy(s->buffer + s->len, frame, len);
memcpy(&s->buffer[s->len], frame, len);
if (s->crc_bytes == 2)
s->crc = crc_itu16_calc(frame, len, (uint16_t) s->crc);
else
@ -589,6 +603,27 @@ SPAN_DECLARE(void) hdlc_tx_set_max_frame_len(hdlc_tx_state_t *s, size_t max_len)
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) hdlc_tx_restart(hdlc_tx_state_t *s)
{
s->octets_in_progress = 0;
s->num_bits = 0;
s->idle_octet = 0x7E;
s->flag_octets = 0;
s->abort_octets = 0;
s->report_flag_underflow = false;
s->len = 0;
s->pos = 0;
if (s->crc_bytes == 2)
s->crc = 0xFFFF;
else
s->crc = 0xFFFFFFFF;
s->byte = 0;
s->bits = 0;
s->tx_end = false;
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(hdlc_tx_state_t *) hdlc_tx_init(hdlc_tx_state_t *s,
bool crc32,
int inter_frame_flags,
@ -602,7 +637,6 @@ SPAN_DECLARE(hdlc_tx_state_t *) hdlc_tx_init(hdlc_tx_state_t *s,
return NULL;
}
memset(s, 0, sizeof(*s));
s->idle_octet = 0x7E;
s->underflow_handler = handler;
s->user_data = user_data;
s->inter_frame_flags = (inter_frame_flags < 1) ? 1 : inter_frame_flags;
@ -616,6 +650,7 @@ SPAN_DECLARE(hdlc_tx_state_t *) hdlc_tx_init(hdlc_tx_state_t *s,
s->crc_bytes = 2;
s->crc = 0xFFFF;
}
s->idle_octet = 0x7E;
s->progressive = progressive;
s->max_frame_len = HDLC_MAXFRAME_LEN;
return s;

Some files were not shown because too many files have changed in this diff Show More