diff --git a/.gitignore b/.gitignore index 5da9566192..b85dc53ca8 100644 --- a/.gitignore +++ b/.gitignore @@ -83,6 +83,7 @@ core.* /build/config/compile /build/config/config.guess +/build/config/config.sub /build/config/depcomp /build/config/install-sh /build/config/ltmain.sh diff --git a/Freeswitch.2008.sln b/Freeswitch.2008.sln index 4f53ccc395..9942878717 100644 --- a/Freeswitch.2008.sln +++ b/Freeswitch.2008.sln @@ -466,6 +466,8 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_dingaling", "src\mod\endpoints\mod_dingaling\mod_dingaling.2008.vcproj", "{FFAA4C52-3A53-4F99-90C1-D59D1F0427F3}" ProjectSection(ProjectDependencies) = postProject {1906D736-08BD-4EE1-924F-B536249B9A54} = {1906D736-08BD-4EE1-924F-B536249B9A54} + {D331904D-A00A-4694-A5A3-FCFF64AB5DBE} = {D331904D-A00A-4694-A5A3-FCFF64AB5DBE} + {B4B62169-5AD4-4559-8707-3D933AC5DB39} = {B4B62169-5AD4-4559-8707-3D933AC5DB39} {202D7A4E-760D-4D0E-AFA1-D7459CED30FF} = {202D7A4E-760D-4D0E-AFA1-D7459CED30FF} {F6C55D93-B927-4483-BB69-15AEF3DD2DFF} = {F6C55D93-B927-4483-BB69-15AEF3DD2DFF} {E727E8F6-935D-46FE-8B0E-37834748A0E3} = {E727E8F6-935D-46FE-8B0E-37834748A0E3} diff --git a/Freeswitch.2010.sln b/Freeswitch.2010.sln index 289d657782..cf7053329a 100644 --- a/Freeswitch.2010.sln +++ b/Freeswitch.2010.sln @@ -716,6 +716,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ldns", "libs\win32\ldns\ldn EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_callcenter", "src\mod\applications\mod_callcenter\mod_callcenter.2010.vcxproj", "{47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_blacklist", "src\mod\applications\mod_blacklist\mod_blacklist.2010.vcxproj", "{50AAC2CE-BFC9-4912-87CC-C6381850D735}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution All|Win32 = All|Win32 @@ -3665,6 +3667,19 @@ Global {47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A}.Release|x64.ActiveCfg = Release|x64 {47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A}.Release|x64 Setup.ActiveCfg = Release|x64 {47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A}.Release|x86 Setup.ActiveCfg = Release|x64 + {50AAC2CE-BFC9-4912-87CC-C6381850D735}.All|Win32.ActiveCfg = Release|x64 + {50AAC2CE-BFC9-4912-87CC-C6381850D735}.All|x64.ActiveCfg = Release|x64 + {50AAC2CE-BFC9-4912-87CC-C6381850D735}.All|x64.Build.0 = Release|x64 + {50AAC2CE-BFC9-4912-87CC-C6381850D735}.All|x64 Setup.ActiveCfg = Release|x64 + {50AAC2CE-BFC9-4912-87CC-C6381850D735}.All|x86 Setup.ActiveCfg = Release|x64 + {50AAC2CE-BFC9-4912-87CC-C6381850D735}.Debug|Win32.ActiveCfg = Debug|Win32 + {50AAC2CE-BFC9-4912-87CC-C6381850D735}.Debug|x64.ActiveCfg = Debug|x64 + {50AAC2CE-BFC9-4912-87CC-C6381850D735}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {50AAC2CE-BFC9-4912-87CC-C6381850D735}.Debug|x86 Setup.ActiveCfg = Debug|x64 + {50AAC2CE-BFC9-4912-87CC-C6381850D735}.Release|Win32.ActiveCfg = Release|Win32 + {50AAC2CE-BFC9-4912-87CC-C6381850D735}.Release|x64.ActiveCfg = Release|x64 + {50AAC2CE-BFC9-4912-87CC-C6381850D735}.Release|x64 Setup.ActiveCfg = Release|x64 + {50AAC2CE-BFC9-4912-87CC-C6381850D735}.Release|x86 Setup.ActiveCfg = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -3714,6 +3729,7 @@ Global {B889A18E-70A7-44B5-B2C9-47798D4F43B3} = {E72B5BCB-6462-4D23-B419-3AF1A4AC3D78} {5C2B4D88-3BEA-4FE0-90DF-FA9836099D5F} = {E72B5BCB-6462-4D23-B419-3AF1A4AC3D78} {47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A} = {E72B5BCB-6462-4D23-B419-3AF1A4AC3D78} + {50AAC2CE-BFC9-4912-87CC-C6381850D735} = {E72B5BCB-6462-4D23-B419-3AF1A4AC3D78} {07113B25-D3AF-4E04-BA77-4CD1171F022C} = {C5F182F9-754A-4EC5-B50F-76ED02BE13F4} {A27CCA23-1541-4337-81A4-F0A6413078A0} = {C5F182F9-754A-4EC5-B50F-76ED02BE13F4} {E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24} = {C5F182F9-754A-4EC5-B50F-76ED02BE13F4} diff --git a/Makefile.am b/Makefile.am index 50cf65fc7a..a9193c99fa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ EXTRA_DIST = SUBDIRS = . src -AUTOMAKE_OPTS = foreign +AUTOMAKE_OPTIONS = foreign NAME = freeswitch AM_CFLAGS = $(SWITCH_AM_CFLAGS) $(SWITCH_ANSI_CFLAGS) @@ -106,6 +106,7 @@ CORE_CFLAGS += -I$(switch_srcdir)/libs/spandsp/src -I$(switch_srcdir)/libs/tiff- CORE_LIBS = libs/apr-util/libaprutil-1.la libs/apr/libapr-1.la CORE_LIBS += libs/sqlite/libsqlite3.la libs/pcre/libpcre.la libs/speex/libspeex/libspeexdsp.la + if ENABLE_SRTP CORE_CFLAGS += -DENABLE_SRTP CORE_LIBS += libs/srtp/libsrtp.la @@ -128,13 +129,17 @@ if ENABLE_TIMERFD_WRAPPER CORE_CFLAGS += -DTIMERFD_WRAP endif +if CURL_BUILTIN +CORE_LIBS += libs/curl/lib/libcurl.la +endif + ## ## libfreeswitch ## lib_LTLIBRARIES = libfreeswitch.la libfreeswitch_la_CFLAGS = $(CORE_CFLAGS) $(AM_CFLAGS) -libfreeswitch_la_LDFLAGS = -version-info 1:0:0 $(AM_LDFLAGS) $(PLATFORM_CORE_DEPLIBS) -libfreeswitch_la_LIBADD = $(CORE_LIBS) +libfreeswitch_la_LDFLAGS = -version-info 1:0:0 $(AM_LDFLAGS) $(PLATFORM_CORE_LDFLAGS) +libfreeswitch_la_LIBADD = $(CORE_LIBS) $(PLATFORM_CORE_LIBS) libfreeswitch_la_DEPENDENCIES = $(BUILT_SOURCES) if HAVE_ODBC @@ -244,6 +249,7 @@ libfreeswitch_la_SOURCES = \ src/switch_pcm.c \ src/switch_profile.c \ src/switch_json.c \ + src/switch_curl.c \ libs/stfu/stfu.c \ libs/libteletone/src/libteletone_detect.c \ libs/libteletone/src/libteletone_generate.c \ @@ -294,21 +300,32 @@ fs_cli_CFLAGS += -DHAVE_EDITLINE -I$(switch_srcdir)/libs/libedit/src fs_cli_LDADD = libs/libedit/src/.libs/libedit.a endif + ## ## fs_encode () ## fs_encode_SOURCES = src/fs_encode.c -fs_encode_CFLAGS = $(AM_CFLAGS) -fs_encode_LDFLAGS = $(AM_LDFLAGS) $(CORE_LIBS) -fs_encode_LDADD = libfreeswitch.la -lcrypt -lrt +fs_encode_CFLAGS = $(AM_CFLAGS) +fs_encode_LDFLAGS = $(AM_LDFLAGS) +fs_encode_LDADD = libfreeswitch.la $(CORE_LIBS) + +if HAVE_ODBC +fs_encode_LDADD += $(ODBC_LIB_FLAGS) +endif + ## ## tone2wav () ## tone2wav_SOURCES = src/tone2wav.c tone2wav_CFLAGS = $(AM_CFLAGS) -tone2wav_LDFLAGS = $(AM_LDFLAGS) $(CORE_LIBS) -tone2wav_LDADD = libfreeswitch.la -lcrypt -lrt +tone2wav_LDFLAGS = $(AM_LDFLAGS) +tone2wav_LDADD = libfreeswitch.la $(CORE_LIBS) + +if HAVE_ODBC +tone2wav_LDADD += $(ODBC_LIB_FLAGS) +endif + ## ## fs_ivrd () @@ -332,6 +349,10 @@ freeswitch_CFLAGS += -Ilibs/libedit/src -DSWITCH_HAVE_LIBEDIT freeswitch_LDADD += libs/libedit/src/.libs/libedit.a endif +if HAVE_ODBC +freeswitch_LDADD += $(ODBC_LIB_FLAGS) +endif + ## ## Scripts @@ -415,6 +436,13 @@ src/include/switch_version.h: src/include/switch_version.h.in .version $(libfree libs/libedit/src/.libs/libedit.a: cd libs/libedit && $(MAKE) +libs/curl/Makefile: + cd libs/curl && sh ./configure.gnu --prefix=$(prefix) + +libs/curl/lib/libcurl.la: libs/curl libs/curl/Makefile + @cd libs/curl && $(MAKE) + @$(TOUCH_TARGET) + libs/apr/libapr-1.la: libs/apr libs/apr/.update @cd libs/apr && $(MAKE) @$(TOUCH_TARGET) @@ -560,7 +588,9 @@ libs/openzap/Makefile: cd libs/openzap && autoconf cd libs/openzap && ./configure -update-clean: clean modwipe uninstall libs/openzap/Makefile python-reconf +reinstall: modwipe uninstall install + +update-clean: clean libs/openzap/Makefile python-reconf cd libs/sofia-sip && $(MAKE) clean cd libs/openzap && $(MAKE) clean cd libs/portaudio && $(MAKE) clean @@ -584,6 +614,11 @@ speex-reconf: cd libs/speex && ./config.status --recheck cd libs/speex && ./config.status +sndfile-reconf: + cd libs/libsndfile && autoreconf + cd libs/libsndfile && ./config.status --recheck + cd libs/libsndfile && ./config.status + tiff-reconf: cd libs/tiff-3.8.2 && autoreconf -fi cd libs/tiff-3.8.2 && sh ./configure.gnu @@ -633,14 +668,14 @@ cluecon: current: cluecon update-clean is-scm $(MAKE) update $(MAKE) all - $(MAKE) install + $(MAKE) reinstall installall: current speedy-current: update-clean is-scm $(MAKE) update $(MAKE) speedy-sure - $(MAKE) install + $(MAKE) reinstall wayclean: clean @@ -661,7 +696,7 @@ modclean: $(switch_builddir)/modules.conf @cd src/mod && $(MAKE) $(AM_MAKEFLAGS) clean modwipe: - rm -f $(prefix)/$(modulesdir)/*.${DYNAMIC_LIB_EXTEN} + rm -f $(modulesdir)/*.${DYNAMIC_LIB_EXTEN} dox: cd docs && doxygen $(PWD)/docs/Doxygen.conf diff --git a/build/config/config.sub b/build/config/config.sub deleted file mode 100755 index 6759825a5b..0000000000 --- a/build/config/config.sub +++ /dev/null @@ -1,1658 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 -# Free Software Foundation, Inc. - -timestamp='2008-01-16' - -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, -2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ - uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray) - os= - basic_machine=$1 - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ - | bfin \ - | c4x | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | fido | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore | mep \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64vr | mips64vrel \ - | mips64orion | mips64orionel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | mt \ - | msp430 \ - | nios | nios2 \ - | ns16k | ns32k \ - | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ - | pyramid \ - | score \ - | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu | strongarm \ - | tahoe | thumb | tic4x | tic80 | tron \ - | v850 | v850e \ - | we32k \ - | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ - | z8k) - basic_machine=$basic_machine-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12) - # Motorola 68HC11/12. - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ - | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nios-* | nios2-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ - | pyramid-* \ - | romp-* | rs6000-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ - | tahoe-* | thumb-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tron-* \ - | v850-* | v850e-* | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc) basic_machine=powerpc-unknown - ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tic54x | c54x*) - basic_machine=tic54x-unknown - os=-coff - ;; - tic55x | c55x*) - basic_machine=tic55x-unknown - os=-coff - ;; - tic6x | c6x*) - basic_machine=tic6x-unknown - os=-coff - ;; - tile*) - basic_machine=tile-unknown - os=-linux-gnu - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - mmix) - basic_machine=mmix-knuth - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -openbsd* | -solidbsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -kaos*) - os=-kaos - ;; - -zvmoe) - os=-zvmoe - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - score-*) - os=-elf - ;; - spu-*) - os=-elf - ;; - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 - ;; - m68*-cisco) - os=-aout - ;; - mep-*) - os=-elf - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-haiku) - os=-haiku - ;; - *-ibm) - os=-aix - ;; - *-knuth) - os=-mmixware - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/build/getlib.sh.in b/build/getlib.sh.in index f328b87d45..a123483a5a 100755 --- a/build/getlib.sh.in +++ b/build/getlib.sh.in @@ -1,58 +1,46 @@ #!/bin/sh -bz="false" - -BUNZIP=/usr/bin/bunzip2 TAR=@TAR@ ZCAT=@ZCAT@ +BZIP=@BZIP@ +XZ=@XZ@ WGET=@WGET@ CURL=@CURL@ -if [ -f "$WGET" ] ; then +if [ -f "$WGET" ]; then DOWNLOAD_CMD=$WGET -else - if [ -f "$CURL" ] ; then - DOWNLOAD_CMD="$CURL -O" - fi +elif [ -f "$CURL" ]; then + DOWNLOAD_CMD="$CURL -O" fi -base=http://files.freeswitch.org/downloads/libs/ -tarfile=$1 -url=`echo $tarfile | grep "://"` - -if [ `echo $tarfile | grep bz2` ] ; then - bz="true" - UNZIPPER=$BUNZIP -else - UNZIPPER=$ZCAT -fi - -if [ ! -z $url ] ; then - base=$tarfile/ +if [ -n "`echo $1 | grep '://'`" ]; then + base=$1/ tarfile=$2 +else + base=http://files.freeswitch.org/downloads/libs/ + tarfile=$1 fi -if [ ! -d $tarfile ] ; then +uncompressed=`echo $tarfile | sed 's/\(\(\.tar\.gz\|\.tar\.bz2\|\.tar\.xz\)\|\(\.tgz\|\.tbz2\)\)$//'` - if [ $bz = "true" ] ; then - uncompressed=`echo $tarfile | sed "s/\.tar\.bz2//g"` - else - uncompressed=`echo $tarfile | sed "s/\.tar\.gz//g"` - uncompressed=`echo $uncompressed | sed "s/\.tgz//g"` - fi +case `echo $tarfile | sed 's/.*\.\([^.]\+\)$/\1/'` in + bz2|tbz2) UNZIPPER=$BZIP ;; + xz) UNZIPPER=$XZ ;; + gz|tgz|*) UNZIPPER=$ZCAT ;; +esac - if [ ! -f $tarfile ] ; then - rm -fr $uncompressed - $DOWNLOAD_CMD $base$tarfile - if [ ! -f $tarfile ] ; then - echo cannot find $tarfile - exit 1 - fi +if [ ! -d $tarfile ]; then + if [ ! -f $tarfile ]; then + rm -fr $uncompressed + $DOWNLOAD_CMD $base$tarfile + if [ ! -f $tarfile ]; then + echo cannot find $tarfile + exit 1 + fi fi - if [ ! -d $uncompressed ] ; then - $UNZIPPER -c -d $tarfile | $TAR xf - + if [ ! -d $uncompressed ]; then + $UNZIPPER -c -d $tarfile | $TAR -xf - fi fi exit 0 - diff --git a/build/modmake.rules.in b/build/modmake.rules.in index 51923ec3dd..00d72f050c 100644 --- a/build/modmake.rules.in +++ b/build/modmake.rules.in @@ -80,20 +80,18 @@ TOUCH_TARGET=@TOUCH_TARGET@ MAKE_OPTS = `test -n "$(VERBOSE)" || echo -s` RECURSE_MODNAME=`pwd | sed -e 's|^.*/||'` RECURSE_SOURCEFILE=`if test -f "$$modname.cpp" -o -f "$(MODDIR)/$$modname.cpp"; then echo "$$modname.cpp"; else echo "$$modname.c"; fi` -RECURSE_OUR_DEPS=`test -z "$(WANT_CURL)" || if test ! -z "$(LIBCURL_DEPS)"; then echo $(CURLLA); fi ` -RECURSE_OUR_CFLAGS=`test -z "$(WANT_CURL)" || echo $(LIBCURL_CPPFLAGS) ; $(LOCAL_INSERT_CFLAGS) ` -RECURSE_OUR_LDFLAGS=`test -z "$(WANT_CURL)" || echo $(LIBCURL) ; $(LOCAL_INSERT_LDFLAGS) ` +RECURSE_OUR_CFLAGS=` $(LOCAL_INSERT_CFLAGS) ` +RECURSE_OUR_LDFLAGS=` $(LOCAL_INSERT_LDFLAGS) ` RECURSE_MODDIR=`if test -z $(MODDIR); then pwd | sed -e 's|$(switch_builddir)|$(switch_srcdir)|'; else echo $(MODDIR); fi` RECURSE_MAKE=+modname="$(RECURSE_MODNAME)" ; \ sourcefile="$(RECURSE_SOURCEFILE)" ; \ osarch=`uname -s` ; \ - ourdefs="$(RECURSE_OUR_DEPS)" ; \ ourcflags="$(RECURSE_OUR_CFLAGS)" ; \ ourldflags="$(RECURSE_OUR_LDFLAGS)" ; \ insertobjs="`$(LOCAL_INSERT_OBJS)`" ; \ moddir="$(RECURSE_MODDIR)" ; \ $(MAKE) $(MAKE_OPTS) MODNAME="$$modname" SOURCEFILE="$$sourcefile" MODDIR="$$moddir" \ - OUR_DEPS="$$ourdefs" OUR_CFLAGS="$$ourcflags" OUR_LDFLAGS="$$ourldflags" OUR_OBJS="$$insertobjs" + OUR_CFLAGS="$$ourcflags" OUR_LDFLAGS="$$ourldflags" OUR_OBJS="$$insertobjs" all: Makefile @$(RECURSE_MAKE) all-modules || exit 1 @@ -136,7 +134,7 @@ LINK_OUTPUT_REDIR=> .libs/$(MODNAME).log || error="yes" ; \ exit 1 ;\ fi -$(MODNAME).$(LIBTOOL_LIB_EXTEN): $(LIBS) $(LOCAL_LIBADD) $(OUR_DEPS) $(LOCAL_OBJS) $(OUR_OBJS) $(MODDIR)/$(SOURCEFILE) $(MODNAME).lo +$(MODNAME).$(LIBTOOL_LIB_EXTEN): $(LIBS) $(LOCAL_LIBADD) $(LOCAL_OBJS) $(OUR_OBJS) $(MODDIR)/$(SOURCEFILE) $(MODNAME).lo @echo Creating $@... @test -d .libs || mkdir .libs @error="";\ diff --git a/conf/autoload_configs/conference.conf.xml b/conf/autoload_configs/conference.conf.xml index d4e5aa60ee..0a47f2da30 100644 --- a/conf/autoload_configs/conference.conf.xml +++ b/conf/autoload_configs/conference.conf.xml @@ -29,6 +29,13 @@ + + + @@ -45,6 +52,8 @@ + + @@ -87,6 +96,9 @@ + + + @@ -100,6 +112,12 @@ + + + + + + diff --git a/conf/autoload_configs/http_cache.conf.xml b/conf/autoload_configs/http_cache.conf.xml new file mode 100644 index 0000000000..4150d6472e --- /dev/null +++ b/conf/autoload_configs/http_cache.conf.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/conf/autoload_configs/modules.conf.xml b/conf/autoload_configs/modules.conf.xml index 5758c1cf89..de4bc40897 100644 --- a/conf/autoload_configs/modules.conf.xml +++ b/conf/autoload_configs/modules.conf.xml @@ -97,6 +97,7 @@ + diff --git a/conf/autoload_configs/osp.conf.xml b/conf/autoload_configs/osp.conf.xml index 419a0033ff..b320dbba88 100644 --- a/conf/autoload_configs/osp.conf.xml +++ b/conf/autoload_configs/osp.conf.xml @@ -47,11 +47,7 @@ - - - - - + diff --git a/conf/autoload_configs/presence_map.conf.xml b/conf/autoload_configs/presence_map.conf.xml new file mode 100644 index 0000000000..8a9d1dde5a --- /dev/null +++ b/conf/autoload_configs/presence_map.conf.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/conf/autoload_configs/spandsp.conf.xml b/conf/autoload_configs/spandsp.conf.xml index aed847fe3d..6f062cc731 100644 --- a/conf/autoload_configs/spandsp.conf.xml +++ b/conf/autoload_configs/spandsp.conf.xml @@ -1,5 +1,40 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/conf/autoload_configs/xml_cdr.conf.xml b/conf/autoload_configs/xml_cdr.conf.xml index 6f8ef0deb5..ac9b1f94d3 100644 --- a/conf/autoload_configs/xml_cdr.conf.xml +++ b/conf/autoload_configs/xml_cdr.conf.xml @@ -27,7 +27,7 @@ - + diff --git a/conf/config.FS0 b/conf/config.FS0 new file mode 100644 index 0000000000..5310142148 --- /dev/null +++ b/conf/config.FS0 @@ -0,0 +1,78 @@ +CountryCode: 1 +AreaCode: 800 +FAXNumber: +1.800.555.1212 +LongDistancePrefix: 1 +InternationalPrefix: 011 +DialStringRules: etc/dialrules +ServerTracing: 0xFFF +SessionTracing: 0xFFF +RecvFileMode: 0600 +LogFileMode: 0600 +DeviceMode: 0600 +RingsBeforeAnswer: 1 +SpeakerVolume: off +GettyArgs: "-h %l dx_%s" +LocalIdentifier: "FS" +TagLineFont: etc/lutRS18.pcf +TagLineFormat: "From %%l|%c|Page %%P of %%T" +MaxRecvPages: 200 +# +# +# Modem-related stuff: should reflect modem command interface +# and hardware connection/cabling (e.g. flow control). +# +ModemType: Class1 # use this to supply a hint + +# +# Enabling this will use the hfaxd-protocol to set Caller*ID +# +#ModemSetOriginCmd: AT+VSID="%s","%d" + +# +# If "glare" during initialization becomes a problem then take +# the modem off-hook during initialization, and then place it +# back on-hook when done. +# +#ModemResetCmds: "ATH1\nAT+VCID=1" # enables CallID display +#ModemReadyCmds: ATH0 + +Class1AdaptRecvCmd: AT+FAR=1 +Class1TMConnectDelay: 400 # counteract quick CONNECT response + +# +# If you have trouble with V.17 receiving or sending, +# you may want to enable one of these, respectively. +# +#Class1RMQueryCmd: "!24,48,72,96" # enable this to disable V.17 receiving +#Class1TMQueryCmd: "!24,48,72,96" # enable this to disable V.17 sending + +# +# You'll likely want Caller*ID display (also displays DID) enabled. +# +ModemResetCmds: AT+VCID=1 # enables CallID display + +# +# The pty does not support changing parity. +# +PagerTTYParity: none + +# +# If you are "missing" Caller*ID data on some calls (but not all) +# and if you do not have adequate glare protection you may want to +# not answer based on RINGs, but rather enable the CallIDAnswerLength +# for NDID, disable AT+VCID=1 and do this: +# +#RingsBeforeAnswer: 0 +#ModemRingResponse: AT+VRID=1 + +# Uncomment DATE and TIME if you really want them, but you probably don't. +#CallIDPattern: "DATE=" +#CallIDPattern: "TIME=" +CallIDPattern: "NMBR=" +CallIDPattern: "NAME=" +CallIDPattern: "ANID=" +#CallIDPattern: "USER=" # username provided by call +#CallIDPattern: "PASS=" # password provided by call +#CallIDPattern: "CDID=" # DID context in call +CallIDPattern: "NDID=" +#CallIDAnswerLength: 4 diff --git a/conf/dialplan/default.xml b/conf/dialplan/default.xml index 020507912c..af7344837e 100644 --- a/conf/dialplan/default.xml +++ b/conf/dialplan/default.xml @@ -181,7 +181,7 @@ - + @@ -244,7 +244,6 @@ --> - @@ -260,9 +259,9 @@ + - diff --git a/conf/lang/en/ivr/sounds.xml b/conf/lang/en/ivr/sounds.xml index b5ccead13a..1e67062061 100644 --- a/conf/lang/en/ivr/sounds.xml +++ b/conf/lang/en/ivr/sounds.xml @@ -82,4 +82,25 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/conf/lang/en/vm/sounds.xml b/conf/lang/en/vm/sounds.xml index 5a090411d7..e58d4904bb 100644 --- a/conf/lang/en/vm/sounds.xml +++ b/conf/lang/en/vm/sounds.xml @@ -365,7 +365,7 @@ - + diff --git a/conf/sip_profiles/external.xml b/conf/sip_profiles/external.xml index 81f8e4a61c..27e76a2edb 100644 --- a/conf/sip_profiles/external.xml +++ b/conf/sip_profiles/external.xml @@ -23,6 +23,8 @@ + + diff --git a/conf/sip_profiles/external/example.xml b/conf/sip_profiles/external/example.xml index 7ac8db1186..70668a9ce5 100644 --- a/conf/sip_profiles/external/example.xml +++ b/conf/sip_profiles/external/example.xml @@ -31,4 +31,8 @@ + + + + diff --git a/conf/sip_profiles/internal.xml b/conf/sip_profiles/internal.xml index 629019fbf4..c9855c4bfe 100644 --- a/conf/sip_profiles/internal.xml +++ b/conf/sip_profiles/internal.xml @@ -43,6 +43,9 @@ + + + @@ -70,7 +73,7 @@ - + @@ -154,6 +157,7 @@ + diff --git a/conf/vars.xml b/conf/vars.xml index f24cc5ccee..4f13a61fbb 100644 --- a/conf/vars.xml +++ b/conf/vars.xml @@ -199,6 +199,10 @@ + + + diff --git a/configure.in b/configure.in index 62977f5fb5..b75a2de39e 100644 --- a/configure.in +++ b/configure.in @@ -40,10 +40,10 @@ AC_DEFINE_UNQUOTED([SWITCH_MOD_DIR],"${modulesdir}",[where to install the module if test "$localstatedir" = "\${prefix}/var" ; then rundir="$prefix/run" - logfiledir="${prefix}/log" + logdir="${prefix}/log" else rundir="$localstatedir/run/freeswitch" - logfiledir="$localstatedir/log/freeswitch" + logdir="$localstatedir/log/freeswitch" fi # Where to put pidfile AC_ARG_WITH([rundir], @@ -51,30 +51,38 @@ AC_ARG_WITH([rundir], AC_SUBST(runtimedir) AC_DEFINE_UNQUOTED([SWITCH_RUN_DIR],"${runtimedir}",[where to put pidfile to]) +AC_ARG_WITH([logfiledir], + [AS_HELP_STRING([--with-logfiledir=DIR], [Put logfiles into this location (default: $localstatedir/log)])], [logfiledir="$withval"], [logfiledir="$logdir"]) AC_SUBST(logfiledir) AC_DEFINE_UNQUOTED([SWITCH_LOG_DIR],"${logfiledir}",[where to put log files]) -dbdir="${prefix}/db" +AC_ARG_WITH([dbdir], + [AS_HELP_STRING([--with-dbdir=DIR], [Put database files into this location (default: $prefix/db)])], [dbdir="$withval"], [dbdir="$prefix/db"]) AC_SUBST(dbdir) AC_DEFINE_UNQUOTED([SWITCH_DB_DIR],"${dbdir}",[where to put db files]) -htdocsdir="${prefix}/htdocs" +AC_ARG_WITH([htdocsdir], + [AS_HELP_STRING([--with-htdocsdir=DIR], [Put html files into this location (default: $prefix/htdocs)])], [htdocsdir="$withval"], [htdocsdir="$prefix/htdocs"]) AC_SUBST(htdocsdir) AC_DEFINE_UNQUOTED([SWITCH_HTDOCS_DIR],"${htdocsdir}",[where to put htdocs files]) -soundsdir="${prefix}/sounds" +AC_ARG_WITH([soundsdir], + [AS_HELP_STRING([--with-soundsdir=DIR], [Put sound files into this location (default: $prefix/sounds)])], [soundsdir="$withval"], [soundsdir="$prefix/sounds"]) AC_SUBST(soundsdir) AC_DEFINE_UNQUOTED([SWITCH_SOUNDS_DIR],"${soundsdir}",[where to put sounds files]) -grammardir="${prefix}/grammar" +AC_ARG_WITH([grammardir], + [AS_HELP_STRING([--with-grammardir=DIR], [Put grammar files into this location (default: $prefix/grammar)])], [grammardir="$withval"], [grammardir="$prefix/grammar"]) AC_SUBST(grammardir) AC_DEFINE_UNQUOTED([SWITCH_GRAMMAR_DIR],"${grammardir}",[where to put grammar files]) -scriptdir="${prefix}/scripts" +AC_ARG_WITH([scriptdir], + [AS_HELP_STRING([--with-scriptdir=DIR], [Put script files into this location (default: $prefix/scripts)])], [scriptdir="$withval"], [scriptdir="$prefix/scripts"]) AC_SUBST(scriptdir) AC_DEFINE_UNQUOTED([SWITCH_SCRIPT_DIR],"${scriptdir}",[where to put script files]) -recordingsdir="${prefix}/recordings" +AC_ARG_WITH([recordingsdir], + [AS_HELP_STRING([--with-recordingsdir=DIR], [Put recordings files into this location (default: $prefix/recordings)])], [recordingsdir="$withval"], [recordingsdir="$prefix/recordings"]) AC_SUBST(recordingsdir) AC_DEFINE_UNQUOTED([SWITCH_RECORDINGS_DIR],"${recordingsdir}",[where to put recording files]) @@ -407,7 +415,8 @@ APR_ADDTO(SWITCH_AM_LDFLAGS, -lresolv) fi ESL_LDFLAGS= -PLATFORM_CORE_DEPLIBS= +PLATFORM_CORE_LDFLAGS= +PLATFORM_CORE_LIBS= # tweak platform specific flags case "$host" in *darwin10.*) @@ -417,23 +426,30 @@ case "$host" in APR_ADDTO(CXXFLAGS, -pipe) APR_REMOVEFROM(SWITCH_AM_CFLAGS, -fPIC) if test "x$enable_core_odbc_support" != "xno"; then - APR_ADDTO(PLATFORM_CORE_DEPLIBS, --framework CoreFoundation) + APR_ADDTO([PLATFORM_CORE_LDFLAGS], [--framework CoreFoundation]) fi + APR_ADDTO([PLATFORM_CORE_LIBS], [-ldl]) ;; *darwin*) APR_ADDTO(SWITCH_AM_CFLAGS, -DMACOSX) APR_REMOVEFROM(SWITCH_AM_CFLAGS, -fPIC) if test "x$enable_core_odbc_support" != "xno"; then - APR_ADDTO(PLATFORM_CORE_DEPLIBS, --framework CoreFoundation) + APR_ADDTO([PLATFORM_CORE_LDFLAGS], [--framework CoreFoundation]) fi + APR_ADDTO([PLATFORM_CORE_LIBS], [-ldl]) ;; *-solaris2*) APR_ADDTO(SWITCH_AM_CFLAGS, -DPATH_MAX=2048 -D__EXTENSIONS__) APR_ADDTO(SWITCH_AM_LDFLAGS, -lsendfile -lresolv -lsocket -lnsl -luuid) APR_ADDTO(ESL_LDFLAGS, -lnsl -lsocket) + APR_ADDTO([PLATFORM_CORE_LIBS], [-ldl -lcrypt -lrt -lsendfile -lresolv -lsocket -lnsl -luuid]) ;; *bsd*) APR_ADDTO(SWITCH_AM_CFLAGS, -I/usr/local/include) + APR_ADDTO([PLATFORM_CORE_LIBS], [-lcrypt -lrt]) + ;; + *linux*) + APR_ADDTO([PLATFORM_CORE_LIBS], [-ldl -lcrypt -lrt]) ;; esac @@ -444,7 +460,8 @@ AC_SUBST(SWITCH_ANSI_CFLAGS) AC_SUBST(SWITCH_AM_CXXFLAGS) AC_SUBST(SWITCH_AM_LDFLAGS) AC_SUBST(ESL_LDFLAGS) -AC_SUBST(PLATFORM_CORE_DEPLIBS) +AC_SUBST(PLATFORM_CORE_LDFLAGS) +AC_SUBST(PLATFORM_CORE_LIBS) AC_SUBST(SOLINK) AC_SUBST(DYNAMIC_LIB_EXTEN) AC_SUBST(LIBTOOL_LIB_EXTEN) @@ -474,7 +491,7 @@ AC_PROG_GCC_TRADITIONAL AC_FUNC_MALLOC AC_TYPE_SIGNAL AC_FUNC_STRFTIME -AC_CHECK_FUNCS([gethostname vasprintf mmap mlock mlockall usleep getifaddrs timerfd_create getdtablesize]) +AC_CHECK_FUNCS([gethostname vasprintf mmap mlock mlockall usleep getifaddrs timerfd_create getdtablesize posix_openpt]) AC_CHECK_FUNCS([sched_setscheduler setpriority setrlimit setgroups initgroups]) AC_CHECK_FUNCS([wcsncmp setgroups asprintf setenv pselect gettimeofday localtime_r gmtime_r strcasecmp stricmp _stricmp]) @@ -485,6 +502,9 @@ AC_CHECK_LIB(rt, clock_getres, [AC_DEFINE(HAVE_CLOCK_GETRES, 1, [Define if you h AC_CHECK_LIB(rt, clock_nanosleep, [AC_DEFINE(HAVE_CLOCK_NANOSLEEP, 1, [Define if you have clock_nanosleep()])]) AC_CHECK_FUNC(socket, , AC_CHECK_LIB(socket, socket)) +AC_CHECK_FILE(/dev/ptmx, [AC_DEFINE(HAVE_DEV_PTMX, 1, [Define if you have /dev/ptmx])]) +AC_CHECK_LIB(util, openpty, [AC_DEFINE(HAVE_OPENPTY, 1, [Define if you have openpty()])]) + AC_CHECK_MEMBERS([struct tm.tm_gmtoff],,,[ #include #include ]) @@ -764,6 +784,8 @@ case $host in ;; esac +AC_PATH_PROGS(BZIP, bzip2) +AC_PATH_PROGS(XZ, xz) AC_PATH_PROGS(TAR, gtar tar) AC_PATH_PROGS(WGET, wget) AC_PATH_PROGS(CURL, curl) @@ -792,12 +814,29 @@ if test "$_libcurl_with" = "yes" ; then ac_cv_use_system_curl=yes; fi +if test "$ac_cv_use_system_curl" = "yes" ; then +AC_CACHE_CHECK([whether to use system libcurl library], [ac_cv_curl_usable], [ + AC_CHECK_LIB(curl, Curl_setopt, [ac_cv_curl_usable="yes"], [ac_cv_curl_usable="no"]) +]) +fi + +if test "$ac_cv_curl_usable" != "yes" ; then + ac_cv_use_system_curl=no; +fi + if test "$ac_cv_use_system_curl" != "yes" ; then LIBCURL_DEPS='${switch_builddir}/libs/curl/lib/libcurl.la' LIBCURL='${switch_builddir}/libs/curl/lib/libcurl.la' LIBCURL_CPPFLAGS='-I${switch_srcdir}/libs/curl/include' +else + SWITCH_AM_LDFLAGS="$LIBCURL $SWITCH_AM_LDFLAGS" fi +SWITCH_AM_CFLAGS="$LIBCURL_CPPFLAGS $SWITCH_AM_CFLAGS" +SWITCH_AM_CXXFLAGS="$LIBCURL_CPPFLAGS $SWITCH_AM_CXXFLAGS" + +AM_CONDITIONAL([CURL_BUILTIN],[test "${ac_cv_use_system_curl}" != "yes"]) + AC_SUBST(LIBCURL_DEPS) @@ -1031,10 +1070,7 @@ AC_CONFIG_SUBDIRS([libs/pcre]) AC_CONFIG_SUBDIRS([libs/apr]) AC_CONFIG_SUBDIRS([libs/apr-util]) AC_CONFIG_SUBDIRS([libs/ilbc]) - -if test "$ac_cv_use_system_curl" != "yes" ; then - AC_CONFIG_SUBDIRS([libs/curl]) -fi +AC_CONFIG_SUBDIRS([libs/curl]) AC_CONFIG_SUBDIRS([libs/iksemel]) AC_CONFIG_SUBDIRS([libs/js/nsprpub]) AC_CONFIG_SUBDIRS([libs/js]) diff --git a/docs/ChangeLog b/docs/ChangeLog index 89ac7f0231..78d8f84d85 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -30,6 +30,7 @@ freeswitch (1.0.7) build: They no longer ship the wsj model in pocketsphinx... and seems the dictionary has moved a bit. (r:23571680) build: unimrcp vs2010 build fixes for new version (r:2dcca5f4) build: add sqlite to clean on make current or update-clean (r:2366f429) + build: Update windows to use Lame 3.98.4 (r:4349ec00) codec2: working prototype, still for testing only (r:04ca0751) config: move limit.conf to db.conf config: Update VM phrase macros to voice option then action on main, config menus @@ -55,6 +56,7 @@ freeswitch (1.0.7) config: Add ivr/ subdir to conf/lang/en/en.xml (r:42f10a48) config: Fix mod_directory phrase file references to 'dir-press.wav' (correct: vm-press) (r:3ef2692f) config: bump ru sounds version to 1.0.13 (r:2b1b19bf) + config: Fix eavesdrop so that *0 works as well as 88 as the access code (r:cbfe83cc) core: Add RTCP support (FSRTP-14) core: handle some errors on missing db handle conditions core: add ... and shutdown as a fail-safe when no modules are loaded @@ -309,6 +311,31 @@ freeswitch (1.0.7) core: fix event firing for CHANNEL_PROGRESS_MEDIA event (r:e2a4fb11/FS-3396) core: add emulation for asterisk DIALSTATUS magic var (r:9d98d49f) core: the new code requires accurate timestamps, we were incrementing it by the interval (20) instead of the samples (160) (r:f10566af/FS-3181) + core: pass cancel_cause into enterprise_originate (r:2e9724d2) + core: add support for global namespace in chat interface to bind to unhandled messages (r:6dd1264d) + core: resolve Syntax Error when using MSSQL in core (r:40990c04/FS-3527) + core: add RTP_BUG_ACCEPT_ANY_PACKETS to disable dropping invalid packets for interop with Oracle CCA (r:aea22cd4) + core: yield when doing b64 encode to avoid stealing the cpu on single proc crappy hardware (r:7d612da4) + core: DTMF stands for Devil Took My Fone (r:0c066f06) + core: add callee_id name/number to xml_cdr (r:bcd1e147) + core: add new flag to frames to denote pass thru frames that are not audio (r:cb9abe02) + core: change -hp to -rp, add -lp and -np, no priority flags means auto which will do -rp if you have > 1 cpu (r:c1dd008b) + core: only reap sigchld when in fork mode for system (r:1e712c7e) + core: Add application flag zombie_exec so registered applications can apply to be executed on channels that are already hungup, like the inline exec this is only limited to a small family of apps that do not use the channel for audio. (r:637a5ed8) + core: do not escape strings inside single quotes unless we can find a closing quote too (r:b4b99c41) + core: convert chat interface to use events instead of a bunch of args (r:9125a96c) + core: make app to turn on new zombie exec instead of always doing it (r:3a2f8183) + core: fix inaccurate sample count in file handle, buffered samples were being double tallied (r:5fe3a22d) + core: prevent sql injection by using sqlite formatter on various code that generates sql stmts with switch_snprintf (r:256a6264) + core: add ivr_menu_terminator variable you can set to none or the dtmf chars you want to terminate input (r:0a3e5d2f) + core: delay_echo was double the length in milliseconds from what it should be (r:3317f5d3) + core: fix issue where clearing a single realm does not completely clear (r:d2710422) + core: add manual_rtp_bug gen_one_gen_all to prevent rtp passthru to break the *S* word.. (r:9e094835) + core: Add transfer_history to logs (r:1bf97fa7) + core: add fsctl sync_clock_when_idle so you can sync the clock but have it not do it till there are 0 calls (r:2094f2d3) + core: add getGlobalVariable and setGlobalVariable to swig stuff (r:2faaee0e) + core: Fix erroneous "module busy" messages on module unload (r:bad5964b/FS-3589) + core: move code from uuid_kill into core (r:3c9551ee) docs: Major clean up of doxygen generated core API documentation (r:794246e1) docs: Add libteletone back to core API documentation (r:c35c138d) embedded languages: Provide core level support for conditional Set Global Variable (r:c017c24b/FSCORE-612) @@ -320,6 +347,10 @@ freeswitch (1.0.7) fs_cli: let ctl-c work until you are connected (r:986f258d) fs_cli: add -i --interrupt to fs_cli to allow control-c to exit the program (r:e7b3c3b1) fs_cli: add timeout option to fs_cli (r:5fad26b4) + fs_cli: implement CLI prompt redrawing (r:a79f1f42) (many other minor changes by TC on 2011-09-22) + fs_cli: implement configurable prompt, input, and output coloring (r:c7ec19d6) + fs_cli: allow ;; seperated commands in fs_cli -x (r:cbc92936) + fs_cli: only enable new features on supported terminals (r:26cd927c) lang: Improve French phrase files (FSCONFIG-23) lang: Update langs - Add pt_PT, update es to have es_ES and es_MX, update mod_say_es and add mod_say_pt (FS-2937) (r:c81a9448/FS-2937) libapr: Fix issue where after a bridge with a member, uuid of Agent is set to single quote character ' (r:3fee704d/FS-2738) @@ -327,6 +358,7 @@ freeswitch (1.0.7) libdingaling: Fix crash in new GV interface when exceeding 24 calls (r:be00609a/FS-2171) libdingaling: fix crash when GV call ends (r:687140b5/FS-3139) libdingaling: fix small leak (r:d3ea42d8/FS-3334) + libdingaling: send keep alive packets to prevent NAT from munging connection (thanks Federico Beffa) (r:4bd305e5/FS-3612) libesl: Fix potential race condition (ESL-36) libesl: Add /uuid command to fs_cli to filter logs by uuid libesl: Increase buffer in fs_cli for Win (r:d1d6be88/FSCORE-611) @@ -358,11 +390,14 @@ freeswitch (1.0.7) libesl: Add digit_timeout to ESL::IVR's playAndGetDigits method (r:f564d383) libesl: add array manipulation to the wraper code (r:ffa0a071) libesl: fix mem leak - good catch, Jlenk! (r:e420e17f/FS-3386) + libesl: add sendmsg function to esl (r:2ae688a3) libfreetdm: implemented freetdm config nodes and ss7 initial configuration libfreetdm: fix codec for CAS signaling (r:b76e7f18) libfreetdm: freetdm: ss7- added support for incoming group blocks, started adding support for ansi (r:c219a73c) + libfreetdm: receive side, update libteletone to track duration so it is less likely to double detect and push api changes down to freetdm (r:a65794fb/FS-3570) libg7221: A bunch of tweaks to the G.722.1 codec (r:5d548570) libgnutls: link to libgcrypt as well, please report any platforms this breaks, but it should be portable (r:c569fb0f/FS-1248) + libiksemel: making this the new default and patching libdingaling to use it exclusively with openssl, now we actually have single thread for gtalk an no gah noodlez (r:f506e19e/FS-3471) libjs: non-portable comment syntax in .s files libldns: select on FD > 1024 get this patch to ldns ppl (r:710fc7a7/FS-3110) libopenzap: Add CLI tracing @@ -402,6 +437,11 @@ freeswitch (1.0.7) mod_avmd: Initial check in - Advanced Voicemail Detect (r:10c6a30a) (by Eric Des Courtis) mod_avmd: Add to windows build (r:df4bd935) mod_avmd: Fix mem leak (r:cd951384/FS-2839) + mod_blacklist: Add mod_blacklist from contrib. (r:3a477c42) + mod_blacklist: Add example configuration file (r:d00f7464) + mod_blacklist: Resource leak fixes, config checks and add help output for api interface (r:41abb3e6) + mod_blacklist: add ability to dump a list back to it's text file (r:1d5f5ec7) + mod_blacklist: fix broken dump/save (r:abc5d7cd/FS-3617) mod_callcenter: Initial commit of the mod_callcenter application. This module is in it early state of developpement. You can see documentation on the wiki at : http://wiki.freeswitch.org/wiki/Mod_callcenter For support/comments, please use http://jira.freeswitch.org/ and select the MOD CALLCENTER module. (r:ba09b96d) mod_callcenter: Add ability to unload/reload/load a queue setting (You still need to reloadxml before). Note that joining a queue will check for it in the config and load it on the fly... I've used the same system as in mod_voicemail. Not sure if we should allow this, but just comment it out of the config before unload and it wont be available anymore (r:3eafca60) mod_callcenter: Try to fix the ring-all, also add cli auto complete done in previous commit (r:1666783c) @@ -438,6 +478,7 @@ freeswitch (1.0.7) mod_callcenter: New strategies: round-robin, random, and 'top-down' (r:2b4b23aa,r:bee247ca) mod_callcenter: Display an warning when MOH is invalid and resume wait with silence. (r:37b14c9a/FS-2740) mod_callcenter: Fix member been switch as abandoned when he was pickup by an agent (r:9ff8f53f/FS-3281) + mod_cdr_mongodb: add MongoDB CDR module (r:a9169199) mod_cdr_sqlite: initial commit (r:f625fe3b) mod_cdr_sqlite: config file for mod_cdr_sqlite (r:25bc8fe3) mod_cdr_sqlite: Drop transaction BEGIN/END around INSERT. We're only executing one command, and autocommit will automatically rollback if the INSERT fails. Sync state_handlers with mod_cdr_csv. Minor libpq fixups. (r:0f95b870) @@ -473,6 +514,9 @@ freeswitch (1.0.7) mod_commands: fix crash when uuid_break all cannot find bonded uuid channel (r:69e61f76/FS-3468) mod_commands: fix uuid_dual_transfer for inline dialplan (r:5d84efc3/FS-3403) mod_commands: update show calls to show both 1 legged calls and bridged calls, also show bridged_calls for previous behaviour of show calls (r:c16c74d9) + mod_commands: Add 'presence_data' field to 'show channels like xxx' list of fields. This makes anthm's trick mentioned on the mailing list even more handy. (r:4872e6ff) + mod_commands: Update tab-complete for show cmd to include bridged_calls, detailed_calls, detailed_bridged_calls and removed distinct_channels (r:2fa8f110) + mod_commands: add threaded-system-exec param and fsctl (set it to false to use fork) (r:910f5364) mod_conference: Fix reporting of volume up/down (MODAPP-419) mod_conference: add last talking time per member to conference xml list mod_conference: add terminate-on-silence conference param @@ -514,6 +558,10 @@ freeswitch (1.0.7) mod_conference: add conference member flag nomoh (r:f35a6814) mod_conference: add hup command to conference (kick without the kick sound) (r:492db906) mod_conference: see H.264 iFrames (r:765be8c9/FS-3406) + mod_conference: add moderator PIN controls (thanks Moy) (r:1936c2b0/FS-3493) + mod_conference: remove waste flags from both conference and member and explicitly always send audio from conferences to avoid random interop issues and general discomfort these flags are now deprecated (r:5d77e789) + mod_conference: add conference cdrs to mod_conference (r:127be02d) + mod_conference: add custom kick sound to conference (r:8fde25cc) mod_curl: use method=post when post requested (r:c6a4ddd0/FSMOD-69) mod_db: fix stack corruption (MODAPP-407) mod_dialplan_xml: Add in the INFO log the caller id number when processing a request (Currenly only show the caller name) (r:e1df5e13) @@ -525,6 +573,9 @@ freeswitch (1.0.7) mod_dingaling: use the login as message source when not in component mode. (chat_send) (r:58c28aab) mod_dingaling: fix mod_dingaling/iksemel/gnutls link error when using newer autotools (r:294b0779/FS-3182) mod_dingaling: fix segmentation fault on mod_dingaling when receiving a discovery from the server (r:2e651c8f/FS-3391) + mod_dingaling: Remove unused but set variables GCC-4.6 -Wunused-but-set-variable (r:0f45b8ba/GCC-4) + mod_dingaling: Add from_jid (r:f0b52ef7/FS-3611) + mod_dingaling: autoflush durning bridge in dingaling (r:bd9317f2) mod_directory: Add variable directory_search_order to allow to search by first name by default is set to "first_name" (r:163ca31f) mod_directory: let mod_directory use non-XML dialplans (r:8895de1b) mod_distributor: Add mod_distributor to VS2010 - not built by default (r:bac79ba1) @@ -549,6 +600,8 @@ freeswitch (1.0.7) mod_dptools: fix small leak in strftime (r:bbbd67ba) mod_dptools: resolve Heap corruption in strftime_api_function -thanks (r:707bd05b/FS-3417) mod_dptools: fix seg on user_recurse_variables reported on the mailing list (r:01b2bd04) + mod_dptools: add digit_action_set_target app that can set the target (direction of the dtmf flow and subsequent channel who gets the events) to self or peer (bridged channel when possible) (r:cf9859ea) + mod_dptools: get rid of digit_action_set target and add target,bind_target params to bind_digit_action (r:42b64ccd) mod_easyroute: Fix possible segfaults and memory leak during unload, and add new setting odbc-retries (r:7fbc47f8/FS-2973) mod_enum: switch mod_enum to use new portable in-tree version (r:2bbc37e3) mod_enum: fix race condition between ldns configure creating ldns/util.h and mod_enum (r:87884c5c) @@ -562,6 +615,7 @@ freeswitch (1.0.7) mod_erlang_event: Rewrite XML fetch conditional wait to be more sane (Reported by James Aimonetti) (r:6941c6eb/FS-2775) mod_erlang_event: Don't urlencode events (and destroy an event after use) (r:4eccdfef) mod_erlang_event Add proper locking for the list of XML bindings (r:9fe440b2) + mod_erlang_event: Fixed a memory leak, too short of connect times across data centers, a deadlock condition with the globals.bindings_rwlock not being released, a buffer overrun possibility or 4, and added the ability to send a body when injecting an event (r:994f9a8c) mod_event_multicast: make multicast loopback configurable (r:97a7668c/FS-3416) mod_event_socket: fix up other users of switch_event_xmlize() to use SWITCH_EVENT_NONE (r:d6eb7562) mod_event_socket: Fix small mem leaks (r:e4f90584/MODEVENT-68) @@ -569,8 +623,12 @@ freeswitch (1.0.7) mod_event_socket: clear unique headers on event_socket filters (r:436413e0) mod_event_socket: Unlock mutex to prevent mortuus obfirmo (r:64bc1938/FS-3156/FS-3157) mod_event_socket: (and mod_erlang_event) make empty apply-inbound-acl config line not deny all (r:8ae9ab5d/FS-3034) + mod_event_socket: allow duplicate headers to be parsed into events received on the wire (r:2b7a830d) + mod_event_socket: add optional format string after myevent (r:7ed7f539) + mod_event_socket: Allow ridiculously long commands over event socket (r:6bbde4e2/FS-3621) mod_event_zmq: Intitial mod_event_zmq code (r:4d554067) mod_event_zmq: Update download file from 2.1.3 to 2.1.4 (2.1.3 tar file is gone from zmq server) (r:0b780702) + mod_event_zmq: Bump to zeromq-2.1.9 (r:3a352e67) mod_fifo: allow multiple dtmf to exit fifo, set fifo_caller_exit_key to specify which (MODAPP-420) mod_fifo: cancel outbound call if customer hangs up (r:cadb4d94) mod_fifo: add taking_calls param to fifo member add and config file (r:821488bf) @@ -584,7 +642,10 @@ freeswitch (1.0.7) mod_fifo: don't seg in edge case error conditions (r:9ee13b72) mod_fifo: set tracking data before enabling hooks (r:34267869) mod_fifo: Fix fifo orbit timeout when not using a chime tested with and without chime (r:7fee1fd1) + mod_fifo: Fix URI (r:26039c57/FS-3548) + mod_fifo: add _continue_ value for fifo orbit exten that just means exit back to the next dp instruction (r:4d6ee827) mod_file_string: Fix segfault when using file string in conference (r:9c40e8e9/FS-3122) + mod_flite: Update to flite 1.5.1 it should sound better now too (r:ecbd1db8) mod_freetdm: Fix for TON and NPI not passed through to channel variables on incoming calls mod_freetdm: add pvt data to freetdm channels fix fxs features (r:9d456900) mod_freetdm: export and import boost custom data (r:edb2d582) @@ -647,6 +708,8 @@ freeswitch (1.0.7) mod_h323: move PTrace level set to FSH323EndPoint::Initialise. partially apply patch from from Peter Olsson, Remove UnLock() when TryLock() failed and DEBUG_RTP_PACKETS directiv e. (r:7b5803f7) mod_h323: set network_addr of caller profile to signaling ip address. (requested by Steven Ayre) (r:072bf5ad) mod_h323: fix race condition on destroying signaling thread in h323 library (r:c22aac0e) + mod_h323: move the switch_rtp_request_port() call from the contructor to FSH323Connection::CreateRealTimeLogicalChannel() - fix rtp port leak. tnx to Peter Olsson. (r:6f4c4ea0) + mod_http_cache: Initial commit of new module (thanks crienzo) (r:c51acfcc/FS-3597) mod_java: fix eventConsumer issue and add flush() method (r:7fd3aff6) mod_java: Allow user defined java methods to be called at startup and shutdown of JVM (r:1339e218/MODLANG-117) mod_json_cdr: Fix segfault in mod_json_cdr.c (r:f347698a/MODEVENT-66) @@ -687,6 +750,7 @@ freeswitch (1.0.7) mod_managed: add additional support (r:5be58aac) mod_managed: add mono 2.8 patch file see FS-2774 (r:6a948bd9/FS-2774) mod_managed: resolve Memory leak in mod_managed by EventBinding and swig delete_switch_event (r:c6048134/FS-3381) + mod_managed: upgrade mono to support 2.8 - MichaelGG (r:1dcac642/FS-2774) mod_mongo: New mod, initial commit; module for MongoDB (http://www.mongodb.org/) (r:dc6ca6f8/FS-3278) mod_mongo: add mapreduce API (r:7c5b5797/FS-3357) mod_mp4v: MP4V-ES passthru for washibechi on IRC @@ -706,6 +770,7 @@ freeswitch (1.0.7) mod_opus: Use libtool archives for linking, add dependencies to fix parallel builds (r:74bbd4be) mod_osp: initial check (Open Settlement Protocol) mod_osp:Changed OSP TCP port from 1080 to 5045. (r:03abefdf) + mod_perl: add chat app to perl (r:18897f9e) mod_pocketsphinx: Update PocketSphinx to the latest builds... only had to make two changes (r:1a39d7fb) mod_pocketsphinx: They no longer ship the wsj model in pocketsphinx... and seems the dictionary has moved a bit. (r:23571680) mod_portaudio: Fix inbound state (CS_ROUTING not CS_INIT) (MODENDP-302) @@ -716,6 +781,7 @@ freeswitch (1.0.7) mod_portaudio: Fix Windows crash (r:94c9cbf6/FS-3498) mod_portaudio_stream: update to specify the channel index (r:d1169d6e) mod_protovm: This is a very early new prototype voicemail ivr system. You need to copy the sounds.xml and make it loadale in the language folder and protovm.conf.xml inside the autoload_configs folder. Configs file will most definitly change. Once stabilized, we make it install those file by default. (r:fb549777) + mod_python: add chat app to python (r:08917021) mod_radius_cdr: Add 'Freeswitch-Direction' av pair (r:a5170df0) mod_radius_cdr: Add 'Freeswitch-Other-Leg-Id' av pair (r:18d29b46) mod_radius_cdr: log errors with the call's uuid (r:fee49b16) @@ -732,6 +798,8 @@ freeswitch (1.0.7) mod_rtmp: CNG frames need to have codec set too (r:36f812d9) mod_rtmp: remove superfluous hangup (r:50817655) mod_rtmp: fix crash when call made from user not in domain (r:a5452174/FS-3353) + mod_rtmp: add params so xml curl can know who's calling the directory request (r:91b73d1f) + mod_rtmp: New feature: param disallow-multiple-registration on user directory logs out all other users on other sessions with the same user:domain pair. (r:624a2921) mod_sangoma_codec: Add sample config file mod_sangoma_codec: added load/noload options for the supported codecs mod_sangoma_codec: rename load/noload to register/noregister @@ -792,6 +860,10 @@ freeswitch (1.0.7) mod_skypopen: refining oss driver, removing audio sync during call (was each 20 secs), audio sync at the tcp interfacing with the skype client (reading more than 20ms worth) (r:891015e6) mod_skypopen: fixed a demented bug (incrementing a variable zeroed in the same loop) maybe responsible for moh sputtering under load on virtual machines (r:43eeeb82) mod_skypopen: avoid accumulating delay on VMs, better debug logging (r:1b4c78bf) + mod_sms: add new chatplan concept and mod_sms. Apps for chat messages: copy new base freeswitch.xml and chatplan dir if you are upgrading on existing config base (r:7333d46d) + mod_sms: fix "format literal and no arguments" warning (r:a0e91001) + mod_sms: allow chatplan apps to have null args (r:4feb26d3) + mod_sms: only ignore events if you matched something on a cp (r:a14b20af) mod_snapshot: fix bad codepaths in mod_snapshot (r:844ac220) mod_sndfile: Add support for .alaw and .ulaw to mod_sndfile (r:facf09b8/MODFORM-41) mod_sndfile: return break in mod_sndfile when seek returns failure (r:564dc7e4) @@ -999,7 +1071,30 @@ freeswitch (1.0.7) mod_sofia: Fix RTP handling bug to allow goofy & undefined behavior (r:77413ba9/FS-3451) mod_sofia: don't allow auto answer on an non-outbound call (r:61ee7fdc) mod_sofia: use the call_id of the original register in the unsolicited notify for MWI (r:53b0ecce) + mod_sofia: Fix caller ID name on bridged appearance (r:7efa4fb2/FS-3532) + mod_sofia: speed up restart speed of profiles (r:fb5f29c2) + mod_sofia: this is actually compliant when mixing ptimes in the same sdp but since iLBC uses its own fmtp for ptime I will add this patch to make it beleive its 20 for the sake of arguement. If you have any other problems with this, set the channel or global variable sdp_m_per_ptime=false to completely disable the default correct behaviour (r:247537a9/FS-3545) + mod_sofia: I missed a few more spots to hack in the exception for iLBC, (thanks for marring my code iLBC ppl) it should work as expected now even with the m_per_ptime on (r:83a78fbf/FS-3545) + mod_sofia: don't turn X-FS- headers into variables, they are reserved for FS specific communication and should not be passed on (r:7d399cce) + mod_sofia: This patch will probably make it work but the bug is actually in the phone, the patch is simply tolerating the bad behaviour. You are correct about the a=sendonly missing, this was fixed in a later revision of the polycom firmware. I suggest that even if this patch works, that you update your phones to a newer firmware, preferably the most recent. (r:7acddfac/FS-3549) + mod_sofia: add auth username to unreg event (r:1b9b3456) + mod_sofia: fix wrong media ip in recover data issue (r:5154b881) + mod_sofia: fix missing ACK that causes Polycom failure (r:408adb8d/FS-3558) + mod_sofia: use bridge_to instead of signal_bond for recovering bridge (r:f4794620) + mod_sofia: save telephony event data for recovery (r:4d1a76ee) + mod_sofia: tighten up the parsing of these boolean vals issue in t38 sdp (r:626b5cb2/FS-3571,FS-3442,FS-957) + mod_sofia: resolve race condition caused by unresponsive host when unregistering the gateway. (r:607c112f/FS-3583) + mod_sofia: only require user and pass in gateway when register is true (r:9e4ca2c2) + mod_sofia: Remove arbitrary 100 ACL limit (r:dd5188f3/FS-3605) + mod_sofia: add t38_pass_broken_boolean to pass the broken boolean behaviour over to the other side of the call when detected (r:afd0e1fc) + mod_sofia: Update handling of sub/notify (fixes broken Snom BLF) (r:51c22811/FS-2877) + mod_sofia: Don't add Contact header to MESSAGE requests, per RFC3428 (libsofia still does it a bit) (r:1f6670e7/FS-3628) + mod_sofia: add presence_map (r:4ee1722f) + mod_sofia: add presence_map config (r:48416707) + mod_sofia: add lookup params to presence_map (r:ea7f6a18) + mod_sofia: add missing mod_sofia indexes (r:40df8d65) mod_soundtouch: updated soundtouch to library 1.5.0 to fix gcc > 4.3 incompatibilities (r:dfb5c629) + mod_soundtouch: Update soundtouch to 1.6.0 to fix FS-3634 (r:d8ae59fd/FS-3634) mod_spandsp: initial checkin of mod_fax/mod_voipcodecs merge into mod_spandsp (r:fa9a59a8) mod_spandsp: rework of new mod_spandsp to have functions broken up into different c files (r:65400642) mod_spandsp: improve duplicate digit detection and add 'min_dup_digit_spacing_ms' channel variable for use with the dtmf detector (r:eab4f246/FSMOD-45) @@ -1021,6 +1116,9 @@ freeswitch (1.0.7) mod_spandsp: add proper tone detect stop (r:8beb10d2/FS-3367) mod_spandsp: add more fax event information (r:0555b702/FS-3345) mod_spandsp: fix memory issue in spandsp_tone_detect (r:8793c2ed) + mod_spandsp: Tweak link order of some libs to fix build on gcc platforms that have ld flag "--as-needed" as default. (r:0db88b59/FS-2873/FS-2874) + mod_spandsp: Fix spandsp_start_fax_detect timeout issue (r:90a6e78d/FS-3619) + mod_spandsp: Add tone_type param to start_fax_detect to handle outbound fax detection (r:d6d18748/FS-3624) mod_spidermonkey: allow vars to be set containing vars from languages (r:5cd072a3) mod_spidermonkey: fix seg in js hangup (r:7d554c11) mod_spidermonkey: Fix mod_spidermonkey build on FreeBSD, (Undefined symbol PR_LocalTimeParameters). (r:3edb8419) @@ -1041,6 +1139,10 @@ freeswitch (1.0.7) mod_valet_parking: pass hold class on transfer (r:76a065ec) mod_valet_parking: add valet_announce_slot variable (r:293d7254) mod_valet_parking: make valet parking reserve a space for 10 seconds to allow time for an attended transfer switcharoo (r:308f44af) + mod_valet_parking: refactor timeout tracker for valet (r:3514c780) + mod_valet_parking: valet_info now returns uuid properly (r:34ddeb75/FS-3613) + mod_valet_parking: add presence to mod_valet_parking subscribe to the lot name for general stats or individual slots to monitor with park+ prefix *note* this used to be used in mod_fifo which now will use queue+ going forward (r:9daa42c1) + mod_valet_parking: lower token freq to 5, put it in a define and have more obvious warning about full lots (r:2f786a07) mod_voicemail: Fix vm_prefs profile lock (MODAPP-417) mod_voicemail: add 'vm-enabled' param (default true) mod_voicemail: fix vm msg being deleted when pressing key to forward to email (MODAPP-403) @@ -1062,12 +1164,16 @@ freeswitch (1.0.7) mod_voicemail: Add 2 new profile settings, db-password-override and allow-empty-password-auth. By default, they have value of their previous behavior. If db-password-override=true, the db password will only be used if present, if not present fallback to the xml config file vm-password. If allow-empty-password-auth=false, it will disable login via a authentication method if there is no password set in the user account (This wont affect voicemail_authorize=true login). (r:a9db642a) mod_voicemail: remove pointless update_mwi() in vm_list api command (r:b952b2b2) mod_voicemail: add message_len to output of vm_list api command (r:77c5000d) + mod_voicemail: use vm_email as notification address if vm_notify_email isn't set (that behavior was in voicemail_leave_main but not in deliver_vm) (r:8974f9d6) + mod_voicemail: better fix for voicemail email key match (r:aff4bcbe/FS-3080) + mod_voicemail: Prevent rewind key from breaking out of message playback (r:923a104b/FS-3637) mod_xml_cdr: add force_process_cdr var to process b leg cdr on a case by case basis when b leg cdr is disabled (XML-17) mod_xml_cdr: add leg param to query string (XML-24) mod_xml_cdr: fix locked sessions (XML-26) mod_xml_cdr: fix minor memory leaks and config bug (r:19253d83/MODEVENT-62) mod_xml_cdr: Fix prefix-a-leg not respected for url submission (r:ea9021a2/FS-2998) mod_xml_cdr: Fix delay to 5 sec from 5000 sec (r:34a38009/FS-2815) + mod_xml_cdr: Accept all 2xx messages, not just "200" (r:d39b7c6b/FS-3593) mod_xml_rpc: Fix crash if unauthorized XML RPC is attempted (r:9835395c/FS-184) scripts: added honeypot.pl and blacklist.pl which add extra SIP security options (r:b6a81ba7) scripts: do simple verification to make sure we are getting IP addresses from VoIP abuse blacklist (r:b0049160) diff --git a/docs/phrase/phrase_en.xml b/docs/phrase/phrase_en.xml index ecdebc9fdf..58d5a3604f 100644 --- a/docs/phrase/phrase_en.xml +++ b/docs/phrase/phrase_en.xml @@ -493,7 +493,7 @@ - + diff --git a/freeswitch.spec b/freeswitch.spec index 416bfd6a8f..f964cd646c 100644 --- a/freeswitch.spec +++ b/freeswitch.spec @@ -434,7 +434,7 @@ APPLICATION_MODULES_AE="applications/mod_avmd applications/mod_callcenter applic applications/mod_distributor applications/mod_dptools applications/mod_easyroute applications/mod_enum \ applications/mod_esf applications/mod_expr applications/mod_blacklist" APPLICATION_MODULES_FM="applications/mod_fifo applications/mod_fsv applications/mod_hash applications/mod_lcr applications/mod_limit \ - applications/mod_memcache" + applications/mod_memcache applications/mod_http_cache" APPLICATION_MODULES_NY="applications/mod_nibblebill applications/mod_redis applications/mod_rss applications/mod_snom \ applications/mod_soundtouch applications/mod_spandsp applications/mod_spy applications/mod_stress \ applications/mod_valet_parking applications/mod_vmd applications/mod_voicemail applications/mod_sms" @@ -774,6 +774,7 @@ fi %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/fax.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/fifo.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/hash.conf.xml +%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/http_cache.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/ivr.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/java.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/lcr.conf.xml @@ -788,6 +789,7 @@ fi %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/pocketsphinx.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/portaudio.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/post_load_modules.conf.xml +%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/presence_map.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/redis.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/rss.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/rtmp.conf.xml @@ -919,6 +921,7 @@ fi %{prefix}/mod/mod_flite.so* %{prefix}/mod/mod_fsv.so* %{prefix}/mod/mod_hash.so* +%{prefix}/mod/mod_http_cache.so* %{prefix}/mod/mod_h26x.so* %{prefix}/mod/mod_ilbc.so* %{prefix}/mod/mod_lcr.so* @@ -1142,6 +1145,8 @@ fi ###################################################################################################################### %changelog * Tue Jun 14 2011 - michal.bielicki@seventhsignal.de +- added mod_http_cache +* Tue Jun 14 2011 - michal.bielicki@seventhsignal.de - added mod_rtmp * Fri Apr 01 2011 - michal.bielicki@seventhsignal.de - added hebrew language stuff diff --git a/libs/.gitignore b/libs/.gitignore index 8dd2b4db57..e0fed1112a 100644 --- a/libs/.gitignore +++ b/libs/.gitignore @@ -70,8 +70,7 @@ missing /broadvoice/src/Makefile.in /broadvoice/src/stamp-h1 /broadvoice/tests/regression_tests.sh -/celt-0.10.0/ -/celt-0.7.1/ +/celt-*/ /Communicator_semi_40.cd_semi_6000/ /curl/curl-config /curl/include/curl/Makefile @@ -116,8 +115,8 @@ missing /curl/src/stamp-h2 /esl/Debug/ /esl/Release/ -/flite-1.3.99/ -/freeradius-client-1.1.6/ +/flite-*/ +/freeradius-client-*/ /freetdm/build/compile /freetdm/COPYING /freetdm/INSTALL @@ -218,11 +217,11 @@ missing /js/nsprpub/pr/src/threads/Makefile /js/nsprpub/pr/tests/dll/Makefile /js/nsprpub/pr/tests/Makefile -/json-c-0.9/ +/json-c-*/ /js/src/jsautocfg.h /js/src/perlconnect/Makefile.PL -/lame-3.97/ -/ldns-1.6.9/ +/lame-*/ +/ldns-*/ /ldns/doc/ldns_manpages /ldns/include/ /ldns/ldns/config.h @@ -294,9 +293,9 @@ missing /libg722_1/tests/regression_tests.sh /libg723_1/ /libg729/ -/libmemcached-0.32/ -/libogg-1.1.3/ -/libshout-2.2.2/ +/libmemcached-*/ +/libogg-*/ +/libshout-*/ /libsndfile/Cfg/compile /libsndfile/doc/Makefile /libsndfile/doc/Makefile.in @@ -336,15 +335,15 @@ missing /libsndfile/tests/test_wrapper.sh /libsndfile/Win32/Makefile /libsndfile/Win32/Makefile.in -/mongo-cxx-driver-v1.8/ +/mongo-cxx-driver-v*/ /mpg123/ -/openldap-2.4.19/ -/openssl-1.0.0a/ +/openldap-*/ +/openssl-*/ /openzap/build/compile /openzap/COPYING /openzap/INSTALL /openzap/Makefile.in -/opus-0.9.0/ +/opus-*/ /pcre/config.h /pcre/Makefile /pcre/Makefile.in @@ -358,7 +357,7 @@ missing /pcre/pcre_stringpiece_unittest /pcre/pcretest /pcre/stamp-h1 -/pocketsphinx-0.7/ +/pocketsphinx-*/ /portaudio/bin/ /portaudio/bin-stamp /portaudio/lib-stamp @@ -501,7 +500,7 @@ missing /sofia-sip/open_c/Makefile.in /sofia-sip/packages/Makefile /sofia-sip/packages/Makefile.in -/sofia-sip/packages/sofia-sip-1.12.10devel.spec +/sofia-sip/packages/sofia-sip-*devel.spec /sofia-sip/s2check/Makefile /sofia-sip/s2check/Makefile.in /sofia-sip/stamp-h1 @@ -516,7 +515,7 @@ missing /sofia-sip/win32/Makefile.in /sounds/ /soundtouch/ -/soundtouch-1.3.1/ +/soundtouch-*/ /spandsp/config-h.in /spandsp/doc/doxygen /spandsp/doc/Makefile @@ -642,7 +641,7 @@ missing /speex/win32/VS2008/speexenc/Makefile.in /speex/win32/VS2008/tests/Makefile /speex/win32/VS2008/tests/Makefile.in -/sphinxbase-0.7/ +/sphinxbase-*/ /sqlite/keywordhash.h /sqlite/lemon /sqlite/lempar.c @@ -667,95 +666,95 @@ missing /srtp/Makefile.in /srtp/test/Makefile /srtp/test/Makefile.in -/tiff-3.8.2/contrib/acorn/Makefile -/tiff-3.8.2/contrib/acorn/Makefile.in -/tiff-3.8.2/contrib/addtiffo/addtiffo -/tiff-3.8.2/contrib/addtiffo/Makefile -/tiff-3.8.2/contrib/addtiffo/Makefile.in -/tiff-3.8.2/contrib/dbs/Makefile -/tiff-3.8.2/contrib/dbs/Makefile.in -/tiff-3.8.2/contrib/dbs/tiff-bi -/tiff-3.8.2/contrib/dbs/tiff-grayscale -/tiff-3.8.2/contrib/dbs/tiff-palette -/tiff-3.8.2/contrib/dbs/tiff-rgb -/tiff-3.8.2/contrib/dbs/xtiff/Makefile -/tiff-3.8.2/contrib/dbs/xtiff/Makefile.in -/tiff-3.8.2/contrib/iptcutil/iptcutil -/tiff-3.8.2/contrib/iptcutil/Makefile -/tiff-3.8.2/contrib/iptcutil/Makefile.in -/tiff-3.8.2/contrib/mac-cw/Makefile -/tiff-3.8.2/contrib/mac-cw/Makefile.in -/tiff-3.8.2/contrib/mac-mpw/Makefile -/tiff-3.8.2/contrib/mac-mpw/Makefile.in -/tiff-3.8.2/contrib/Makefile -/tiff-3.8.2/contrib/Makefile.in -/tiff-3.8.2/contrib/mfs/Makefile -/tiff-3.8.2/contrib/mfs/Makefile.in -/tiff-3.8.2/contrib/ojpeg/Makefile -/tiff-3.8.2/contrib/ojpeg/Makefile.in -/tiff-3.8.2/contrib/pds/Makefile -/tiff-3.8.2/contrib/pds/Makefile.in -/tiff-3.8.2/contrib/ras/Makefile -/tiff-3.8.2/contrib/ras/Makefile.in -/tiff-3.8.2/contrib/stream/Makefile -/tiff-3.8.2/contrib/stream/Makefile.in -/tiff-3.8.2/contrib/tags/Makefile -/tiff-3.8.2/contrib/tags/Makefile.in -/tiff-3.8.2/contrib/win_dib/Makefile -/tiff-3.8.2/contrib/win_dib/Makefile.in -/tiff-3.8.2/html/images/Makefile -/tiff-3.8.2/html/images/Makefile.in -/tiff-3.8.2/html/Makefile -/tiff-3.8.2/html/Makefile.in -/tiff-3.8.2/html/man/Makefile -/tiff-3.8.2/html/man/Makefile.in -/tiff-3.8.2/libtiff/Makefile -/tiff-3.8.2/libtiff/Makefile.in -/tiff-3.8.2/libtiff/mkg3states -/tiff-3.8.2/libtiff/stamp-h1 -/tiff-3.8.2/libtiff/stamp-h2 -/tiff-3.8.2/libtiff/tif_config.h -/tiff-3.8.2/libtiff/tif_config.h.in -/tiff-3.8.2/libtiff/tiffconf.h -/tiff-3.8.2/m4/libtool.m4 -/tiff-3.8.2/m4/lt~obsolete.m4 -/tiff-3.8.2/m4/ltoptions.m4 -/tiff-3.8.2/m4/ltsugar.m4 -/tiff-3.8.2/m4/ltversion.m4 -/tiff-3.8.2/Makefile -/tiff-3.8.2/Makefile.in -/tiff-3.8.2/man/Makefile -/tiff-3.8.2/man/Makefile.in -/tiff-3.8.2/port/Makefile -/tiff-3.8.2/port/Makefile.in -/tiff-3.8.2/test/Makefile -/tiff-3.8.2/test/Makefile.in -/tiff-3.8.2/tiff-Makefile.tgz -/tiff-3.8.2/tools/bmp2tiff -/tiff-3.8.2/tools/fax2ps -/tiff-3.8.2/tools/fax2tiff -/tiff-3.8.2/tools/gif2tiff -/tiff-3.8.2/tools/Makefile -/tiff-3.8.2/tools/Makefile.in -/tiff-3.8.2/tools/pal2rgb -/tiff-3.8.2/tools/ppm2tiff -/tiff-3.8.2/tools/ras2tiff -/tiff-3.8.2/tools/raw2tiff -/tiff-3.8.2/tools/rgb2ycbcr -/tiff-3.8.2/tools/thumbnail -/tiff-3.8.2/tools/tiff2bw -/tiff-3.8.2/tools/tiff2pdf -/tiff-3.8.2/tools/tiff2ps -/tiff-3.8.2/tools/tiff2rgba -/tiff-3.8.2/tools/tiffcmp -/tiff-3.8.2/tools/tiffcp -/tiff-3.8.2/tools/tiffdither -/tiff-3.8.2/tools/tiffdump -/tiff-3.8.2/tools/tiffgt -/tiff-3.8.2/tools/tiffinfo -/tiff-3.8.2/tools/tiffmedian -/tiff-3.8.2/tools/tiffset -/tiff-3.8.2/tools/tiffsplit +/tiff-*/contrib/acorn/Makefile +/tiff-*/contrib/acorn/Makefile.in +/tiff-*/contrib/addtiffo/addtiffo +/tiff-*/contrib/addtiffo/Makefile +/tiff-*/contrib/addtiffo/Makefile.in +/tiff-*/contrib/dbs/Makefile +/tiff-*/contrib/dbs/Makefile.in +/tiff-*/contrib/dbs/tiff-bi +/tiff-*/contrib/dbs/tiff-grayscale +/tiff-*/contrib/dbs/tiff-palette +/tiff-*/contrib/dbs/tiff-rgb +/tiff-*/contrib/dbs/xtiff/Makefile +/tiff-*/contrib/dbs/xtiff/Makefile.in +/tiff-*/contrib/iptcutil/iptcutil +/tiff-*/contrib/iptcutil/Makefile +/tiff-*/contrib/iptcutil/Makefile.in +/tiff-*/contrib/mac-cw/Makefile +/tiff-*/contrib/mac-cw/Makefile.in +/tiff-*/contrib/mac-mpw/Makefile +/tiff-*/contrib/mac-mpw/Makefile.in +/tiff-*/contrib/Makefile +/tiff-*/contrib/Makefile.in +/tiff-*/contrib/mfs/Makefile +/tiff-*/contrib/mfs/Makefile.in +/tiff-*/contrib/ojpeg/Makefile +/tiff-*/contrib/ojpeg/Makefile.in +/tiff-*/contrib/pds/Makefile +/tiff-*/contrib/pds/Makefile.in +/tiff-*/contrib/ras/Makefile +/tiff-*/contrib/ras/Makefile.in +/tiff-*/contrib/stream/Makefile +/tiff-*/contrib/stream/Makefile.in +/tiff-*/contrib/tags/Makefile +/tiff-*/contrib/tags/Makefile.in +/tiff-*/contrib/win_dib/Makefile +/tiff-*/contrib/win_dib/Makefile.in +/tiff-*/html/images/Makefile +/tiff-*/html/images/Makefile.in +/tiff-*/html/Makefile +/tiff-*/html/Makefile.in +/tiff-*/html/man/Makefile +/tiff-*/html/man/Makefile.in +/tiff-*/libtiff/Makefile +/tiff-*/libtiff/Makefile.in +/tiff-*/libtiff/mkg3states +/tiff-*/libtiff/stamp-h1 +/tiff-*/libtiff/stamp-h2 +/tiff-*/libtiff/tif_config.h +/tiff-*/libtiff/tif_config.h.in +/tiff-*/libtiff/tiffconf.h +/tiff-*/m4/libtool.m4 +/tiff-*/m4/lt~obsolete.m4 +/tiff-*/m4/ltoptions.m4 +/tiff-*/m4/ltsugar.m4 +/tiff-*/m4/ltversion.m4 +/tiff-*/Makefile +/tiff-*/Makefile.in +/tiff-*/man/Makefile +/tiff-*/man/Makefile.in +/tiff-*/port/Makefile +/tiff-*/port/Makefile.in +/tiff-*/test/Makefile +/tiff-*/test/Makefile.in +/tiff-*/tiff-Makefile.tgz +/tiff-*/tools/bmp2tiff +/tiff-*/tools/fax2ps +/tiff-*/tools/fax2tiff +/tiff-*/tools/gif2tiff +/tiff-*/tools/Makefile +/tiff-*/tools/Makefile.in +/tiff-*/tools/pal2rgb +/tiff-*/tools/ppm2tiff +/tiff-*/tools/ras2tiff +/tiff-*/tools/raw2tiff +/tiff-*/tools/rgb2ycbcr +/tiff-*/tools/thumbnail +/tiff-*/tools/tiff2bw +/tiff-*/tools/tiff2pdf +/tiff-*/tools/tiff2ps +/tiff-*/tools/tiff2rgba +/tiff-*/tools/tiffcmp +/tiff-*/tools/tiffcp +/tiff-*/tools/tiffdither +/tiff-*/tools/tiffdump +/tiff-*/tools/tiffgt +/tiff-*/tools/tiffinfo +/tiff-*/tools/tiffmedian +/tiff-*/tools/tiffset +/tiff-*/tools/tiffsplit /unimrcp/build/acmacros/libtool.m4 /unimrcp/build/acmacros/lt~obsolete.m4 /unimrcp/build/acmacros/ltoptions.m4 @@ -904,8 +903,8 @@ missing !/portaudio/bindings/cpp/build/gnu/config.sub !/portaudio/bindings/cpp/build/gnu/configure !/portaudio/bindings/cpp/build/gnu/install-sh -!/tiff-3.8.2/config/depcomp -!/tiff-3.8.2/config/missing +!/tiff-*/config/depcomp +!/tiff-*/config/missing !/xmlrpc-c/install-sh !/xmlrpc-c/missing !/yaml/aclocal.m4 diff --git a/libs/curl/include/curl/curl.h b/libs/curl/include/curl/curl.h index 056e6df745..04ba3d3e63 100644 --- a/libs/curl/include/curl/curl.h +++ b/libs/curl/include/curl/curl.h @@ -304,7 +304,8 @@ typedef enum { CURLE_UNSUPPORTED_PROTOCOL, /* 1 */ CURLE_FAILED_INIT, /* 2 */ CURLE_URL_MALFORMAT, /* 3 */ - CURLE_URL_MALFORMAT_USER, /* 4 - NOT USED */ + CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for + 7.17.0, reused in April 2011 for 7.21.5] */ CURLE_COULDNT_RESOLVE_PROXY, /* 5 */ CURLE_COULDNT_RESOLVE_HOST, /* 6 */ CURLE_COULDNT_CONNECT, /* 7 */ diff --git a/libs/curl/lib/ssluse.c b/libs/curl/lib/ssluse.c index d7b2870c6b..dfbe7a7cf0 100644 --- a/libs/curl/lib/ssluse.c +++ b/libs/curl/lib/ssluse.c @@ -1190,8 +1190,13 @@ Curl_ossl_connect_step1(struct connectdata *conn, req_method = TLSv1_client_method(); break; case CURL_SSLVERSION_SSLv2: +#ifdef OPENSSL_NO_SSL2 + failf(data, "OpenSSL was built without SSLv2 support"); + return CURLE_NOT_BUILT_IN; +#else req_method = SSLv2_client_method(); break; +#endif case CURL_SSLVERSION_SSLv3: req_method = SSLv3_client_method(); break; diff --git a/libs/curl/lib/strerror.c b/libs/curl/lib/strerror.c index 66de7d5570..3c514cb8a1 100644 --- a/libs/curl/lib/strerror.c +++ b/libs/curl/lib/strerror.c @@ -69,6 +69,10 @@ curl_easy_strerror(CURLcode error) case CURLE_URL_MALFORMAT: return "URL using bad/illegal format or missing URL"; + case CURLE_NOT_BUILT_IN: + return "A requested feature, protocol or option was not found built-in in" + " this libcurl due to a build-time decision."; + case CURLE_COULDNT_RESOLVE_PROXY: return "couldn't resolve proxy name"; @@ -278,7 +282,6 @@ curl_easy_strerror(CURLcode error) return "caller must register CURLOPT_CONV_ callback options"; /* error codes not used by current libcurl */ - case CURLE_URL_MALFORMAT_USER: case CURLE_FTP_USER_PASSWORD_INCORRECT: case CURLE_MALFORMAT_USER: case CURLE_BAD_CALLING_ORDER: diff --git a/libs/esl/fs_cli.c b/libs/esl/fs_cli.c index 0f432f464f..53d1bdfce4 100644 --- a/libs/esl/fs_cli.c +++ b/libs/esl/fs_cli.c @@ -72,6 +72,7 @@ static char prompt_str[512] = ""; static char prompt_color[12] = {ESL_SEQ_DEFAULT_COLOR}; static char input_text_color[12] = {ESL_SEQ_DEFAULT_COLOR}; static char output_text_color[12] = {ESL_SEQ_DEFAULT_COLOR}; +static int feature_level = 0; static cli_profile_t profiles[128] = {{{0}}}; static cli_profile_t internal_profile = {{ 0 }}; static int pcount = 0; @@ -237,7 +238,7 @@ static int console_bufferInput (char *addchars, int len, char *cmd, int key) return 0; } if (key == KEY_TAB) { - esl_console_complete(cmd, cmd+iCmdBuffer, &cmd[iCmdBuffer-1]); + esl_console_complete(cmd, cmd+iCmdBuffer, cmd+iCmdBuffer); return 0; } if (key == KEY_UP || key == KEY_DOWN || key == CLEAR_OP) { @@ -680,9 +681,10 @@ static void *msg_thread_run(esl_thread_t *me, void *obj) } #ifndef WIN32 if (aok) { - clear_line(); + if (feature_level) clear_line(); printf("%s%s", colors[level], handle->last_event->body); - redisplay(); + if (!feature_level) printf("%s", ESL_SEQ_DEFAULT_COLOR); + if (feature_level) redisplay(); } #else if (aok) { @@ -1112,6 +1114,7 @@ int main(int argc, char *argv[]) char dft_cfile[512] = "nbess7_cli.conf"; #endif char *home = getenv("HOME"); + char *term = getenv("TERM"); /* Vars for optargs */ int opt; static struct option options[] = { @@ -1146,6 +1149,17 @@ int main(int argc, char *argv[]) int argv_quiet = 0; int loops = 2, reconnect = 0, timeout = 0; + if (term && (!strncasecmp("screen", term, 6) || + !strncasecmp("vt100", term, 5))) { + feature_level = 1; + } else { + feature_level = 0; + } + +#ifdef WIN32 + feature_level = 0; +#endif + strncpy(internal_profile.host, "127.0.0.1", sizeof(internal_profile.host)); strncpy(internal_profile.pass, "ClueCon", sizeof(internal_profile.pass)); strncpy(internal_profile.name, "internal", sizeof(internal_profile.name)); @@ -1279,11 +1293,11 @@ int main(int argc, char *argv[]) snprintf(prompt_str, sizeof(prompt_str), PROMPT_PREFIX "@%s> ", profile->name); } bare_prompt_str_len = (int)strlen(bare_prompt_str); -#ifdef WIN32 - snprintf(prompt_str, sizeof(prompt_str), "%s", bare_prompt_str); /* Not supporting this for now */ -#else - snprintf(prompt_str, sizeof(prompt_str), "%s%s%s", prompt_color, bare_prompt_str, input_text_color); -#endif + if (feature_level) { + snprintf(prompt_str, sizeof(prompt_str), "%s%s%s", prompt_color, bare_prompt_str, input_text_color); + } else { + snprintf(prompt_str, sizeof(prompt_str), "%s", bare_prompt_str); + } connect: connected = 0; while (--loops > 0) { @@ -1310,7 +1324,7 @@ int main(int argc, char *argv[]) } if (argv_exec) { const char *err = NULL; - snprintf(cmd_str, sizeof(cmd_str), "api %s\n\n", argv_command); + snprintf(cmd_str, sizeof(cmd_str), "api %s\nconsole_execute: true\n\n", argv_command); if (timeout) { esl_status_t status = esl_send_recv_timed(&handle, cmd_str, timeout); if (status != ESL_SUCCESS) { diff --git a/libs/esl/ivrd.c b/libs/esl/ivrd.c index 842ef6be13..4066327257 100644 --- a/libs/esl/ivrd.c +++ b/libs/esl/ivrd.c @@ -42,11 +42,6 @@ static void mycallback(esl_socket_t server_sock, esl_socket_t client_sock, struc char path_buffer[1024] = { 0 }; const char *path; - if (fork()) { - close(client_sock); - return; - } - if (esl_attach_handle(&handle, client_sock, addr) != ESL_SUCCESS || !handle.info_event) { esl_log(ESL_LOG_ERROR, "Socket Error\n"); exit(0); @@ -95,9 +90,7 @@ int main(int argc, char *argv[]) return -1; } - signal(SIGCHLD, SIG_IGN); - - esl_listen(ip, port, mycallback); + esl_listen(ip, port, mycallback, 100000); return 0; } diff --git a/libs/esl/src/esl.c b/libs/esl/src/esl.c index 0c387e79ef..5159166ce9 100644 --- a/libs/esl/src/esl.c +++ b/libs/esl/src/esl.c @@ -53,10 +53,18 @@ #ifndef WIN32 #define closesocket(x) close(x) #include +#include #else #pragma warning (disable:6386) /* These warnings need to be ignored warning in sdk header */ #include +#include +#ifndef errno +#define errno WSAGetLastError() +#endif +#ifndef EINTR +#define EINTR WSAEINTR +#endif #pragma warning (default:6386) #endif @@ -612,12 +620,31 @@ static int esl_socket_reuseaddr(esl_socket_t socket) #endif } -ESL_DECLARE(esl_status_t) esl_listen(const char *host, esl_port_t port, esl_listen_callback_t callback) +struct thread_handler { + esl_listen_callback_t callback; + esl_socket_t server_sock; + esl_socket_t client_sock; + struct sockaddr_in addr; +}; + +static void *client_thread(esl_thread_t *me, void *obj) +{ + struct thread_handler *handler = (struct thread_handler *) obj; + + handler->callback(handler->server_sock, handler->client_sock, &handler->addr); + free(handler); + + return NULL; + +} + +ESL_DECLARE(esl_status_t) esl_listen(const char *host, esl_port_t port, esl_listen_callback_t callback, int max) { esl_socket_t server_sock = ESL_SOCK_INVALID; struct sockaddr_in addr; esl_status_t status = ESL_SUCCESS; - + struct thread_handler *handler = NULL; + if ((server_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { return ESL_FAIL; } @@ -634,7 +661,7 @@ ESL_DECLARE(esl_status_t) esl_listen(const char *host, esl_port_t port, esl_list goto end; } - if (listen(server_sock, 10000) < 0) { + if (listen(server_sock, max) < 0) { status = ESL_FAIL; goto end; } @@ -655,7 +682,16 @@ ESL_DECLARE(esl_status_t) esl_listen(const char *host, esl_port_t port, esl_list goto end; } - callback(server_sock, client_sock, &echoClntAddr); + handler = malloc(sizeof(*handler)); + esl_assert(handler); + + memset(handler, 0, sizeof(*handler)); + handler->callback = callback; + handler->server_sock = server_sock; + handler->client_sock = client_sock; + handler->addr = echoClntAddr; + + esl_thread_create_detached(client_thread, handler); } end: @@ -1055,7 +1091,21 @@ ESL_DECLARE(esl_status_t) esl_recv_event_timed(esl_handle_t *handle, uint32_t ms static esl_ssize_t handle_recv(esl_handle_t *handle, void *data, esl_size_t datalen) { - return recv(handle->sock, data, datalen, 0); + int activity; + + while (handle->connected) { + activity = esl_wait_sock(handle->sock, 1000, ESL_POLL_READ|ESL_POLL_ERROR); + + if (activity > 0 && (activity & ESL_POLL_READ)) { + return recv(handle->sock, data, datalen, 0); + } + + if (activity < 0) { + return errno == EINTR ? 0 : -1; + } + } + + return -1; } ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_event_t **save_event) diff --git a/libs/esl/src/include/esl.h b/libs/esl/src/include/esl.h index 74fd2342a5..2f1a50949a 100644 --- a/libs/esl/src/include/esl.h +++ b/libs/esl/src/include/esl.h @@ -391,7 +391,7 @@ ESL_DECLARE(esl_status_t) esl_attach_handle(esl_handle_t *handle, esl_socket_t s \param port Port to bind to \param callback Callback that will be called upon data received */ -ESL_DECLARE(esl_status_t) esl_listen(const char *host, esl_port_t port, esl_listen_callback_t callback); +ESL_DECLARE(esl_status_t) esl_listen(const char *host, esl_port_t port, esl_listen_callback_t callback, int max); /*! \brief Executes application with sendmsg to a specific UUID. Used for outbound socket. \param handle Handle that the msg will be sent diff --git a/libs/esl/testserver.c b/libs/esl/testserver.c index 2e398055e5..cf60313fe7 100644 --- a/libs/esl/testserver.c +++ b/libs/esl/testserver.c @@ -9,11 +9,6 @@ static void mycallback(esl_socket_t server_sock, esl_socket_t client_sock, struc esl_status_t status; time_t exp = 0; - if (fork()) { - close(client_sock); - return; - } - esl_attach_handle(&handle, client_sock, addr); esl_log(ESL_LOG_INFO, "Connected! %d\n", handle.sock); @@ -53,7 +48,7 @@ static void mycallback(esl_socket_t server_sock, esl_socket_t client_sock, struc int main(void) { esl_global_set_default_logger(7); - esl_listen("localhost", 8084, mycallback); + esl_listen("localhost", 8084, mycallback, 100000); return 0; } diff --git a/libs/freetdm/Makefile.am b/libs/freetdm/Makefile.am index 3a88b5f521..35f1cecd1e 100644 --- a/libs/freetdm/Makefile.am +++ b/libs/freetdm/Makefile.am @@ -184,9 +184,9 @@ endif if HAVE_LIBPRI mod_LTLIBRARIES += ftmod_libpri.la ftmod_libpri_la_SOURCES = $(SRC)/ftmod/ftmod_libpri/ftmod_libpri.c $(SRC)/ftmod/ftmod_libpri/lpwrap_pri.c -ftmod_libpri_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) -ftmod_libpri_la_LDFLAGS = -shared -module -avoid-version -lpri -ftmod_libpri_la_LIBADD = libfreetdm.la +ftmod_libpri_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) $(LIBPRI_CPPFLAGS) +ftmod_libpri_la_LDFLAGS = -shared -module -avoid-version $(LIBPRI_LDFLAGS) +ftmod_libpri_la_LIBADD = libfreetdm.la $(LIBPRI_LIBS) endif if HAVE_PRITAP @@ -251,7 +251,7 @@ endif if HAVE_MISDN mod_LTLIBRARIES += ftmod_misdn.la ftmod_misdn_la_SOURCES = $(SRC)/ftmod/ftmod_misdn/ftmod_misdn.c -ftmod_misdn_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) $(MISDN_CFLAGS) +ftmod_misdn_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) $(MISDN_CFLAGS) -D_GNU_SOURCE ftmod_misdn_la_LDFLAGS = -shared -module -avoid-version ftmod_misdn_la_LIBADD = libfreetdm.la endif diff --git a/libs/freetdm/acinclude.m4 b/libs/freetdm/acinclude.m4 index 908ddba855..097278b6ef 100644 --- a/libs/freetdm/acinclude.m4 +++ b/libs/freetdm/acinclude.m4 @@ -1 +1,2 @@ +m4_include([build/ax_compiler_vendor.m4]) m4_include([build/libpcap.m4]) diff --git a/libs/freetdm/configure.ac b/libs/freetdm/configure.ac index a69618ba6f..292c1e7cfa 100644 --- a/libs/freetdm/configure.ac +++ b/libs/freetdm/configure.ac @@ -54,7 +54,7 @@ fi AC_SUBST([confdir]) -DEFAULT_INCLUDES="-I. -I./src/include -I$(srcdir)" +DEFAULT_INCLUDES="-I. -I./src/include -I\$(srcdir)" AC_SUBST([DEFAULT_INCLUDES]) # Where to install the modules @@ -194,28 +194,46 @@ AM_CONDITIONAL([HAVE_OPENR2], [test "${HAVE_OPENR2}" = "yes"]) # HAVE_LIBPRI="no" AC_ARG_WITH([libpri], - [AS_HELP_STRING([--with-libpri], [Install ftmod_libpri])], + [AS_HELP_STRING([--with-libpri@<:@=PREFIX@:>@], [Install ftmod_libpri])], [case "${withval}" in - no) enable_libpri="no" ;; - *) enable_libpri="yes" ;; + no|yes) with_libpri="${withval}" ;; + *) AS_IF([test -d "${withval}"], + [with_libpri="${withval}"], + [AC_MSG_ERROR([Invalid argument for --with-libpri, \"${withval}\" is not a directory])] + ) ;; esac], - [enable_libpri="no"] + [with_libpri="no"] ) -if test "${enable_libpri}" != "no" +if test "x${with_libpri}" != "xno" then + save_LIBS="${LIBS}" + save_CPPFLAGS="${CPPFLAGS}" + save_LDFLAGS="${LDFLAGS}" + + LIBPRI_CPPFLAGS="" + LIBPRI_LDFLAGS="" + AC_MSG_RESULT([${as_nl}<<>> Digium libpri]) - save_LIBS="${LIBS}" + AS_IF([test "x${with_libpri}" != "xyes"], + [LIBPRI_CPPFLAGS="-I${with_libpri}/include" + LIBPRI_LDFLAGS="-L${with_libpri}/lib"], + ) + + LDFLAGS="${save_LDFLAGS} ${LIBPRI_LDFLAGS}" + CPPFLAGS="${save_CPPFLAGS} ${LIBPRI_CPPFLAGS}" LIBS="${LIBS} -lpri" + AC_MSG_CHECKING([whether libpri is usable]) AC_LINK_IFELSE( [AC_LANG_PROGRAM( [#include ], [const char *version = pri_get_version();] )], - [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([yes]) + HAVE_LIBPRI="yes"], [AC_MSG_RESULT([no]) - AC_MSG_ERROR([libpri is not installed or unusable (see config.log for details)])] + AC_MSG_ERROR([libpri not found or unusable (see config.log for details)])] ) AC_MSG_CHECKING([whether libpri has BRI support]) @@ -241,10 +259,17 @@ then [AC_MSG_RESULT([no]) AC_MSG_NOTICE([You will need libpri-1.4.12_beta1 or newer for AOC event support])] ) + + # libpri is available, set variables for Makefile(.am) + AC_SUBST([LIBPRI_LIBS], [-lpri]) + AC_SUBST([LIBPRI_LDFLAGS]) + AC_SUBST([LIBPRI_CPPFLAGS]) + LIBS="${save_LIBS}" + LDFLAGS="${save_LDFLAGS}" + CPPFLAGS="${save_CPPFLAGS}" fi -HAVE_LIBPRI="${enable_libpri}" -AM_CONDITIONAL([HAVE_LIBPRI],[test "${enable_libpri}" = "yes"]) +AM_CONDITIONAL([HAVE_LIBPRI],[test "x${HAVE_LIBPRI}" = "xyes"]) ## # Sangoma Wanpipe diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.2008.vcproj b/libs/freetdm/mod_freetdm/mod_freetdm.2008.vcproj index 5ed38903e7..3fdd92af05 100644 --- a/libs/freetdm/mod_freetdm/mod_freetdm.2008.vcproj +++ b/libs/freetdm/mod_freetdm/mod_freetdm.2008.vcproj @@ -45,7 +45,7 @@ Disabled - ../../../src/include;../src/include;../src/isdn/include;%(AdditionalIncludeDirectories) + ../../../src/include;../src/include;../../curl/include;../src/isdn/include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions) true EnableFastChecks @@ -117,7 +117,7 @@ - ../../../src/include;../src/include;../src/isdn/include;%(AdditionalIncludeDirectories) + ../../../src/include;../src/include;../../curl/include;../src/isdn/include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions) MultiThreadedDLL @@ -148,7 +148,7 @@ Disabled - ../../../src/include;../src/include;../src/isdn/include;%(AdditionalIncludeDirectories) + ../../../src/include;../src/include;../../curl/include;../src/isdn/include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions) true EnableFastChecks @@ -177,7 +177,7 @@ X64 - ../../../src/include;../src/include;../src/isdn/include;%(AdditionalIncludeDirectories) + ../../../src/include;../src/include;../../curl/include;../src/isdn/include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions) MultiThreadedDLL diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 055040858f..0fc7906331 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -507,7 +507,7 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) const char *name = NULL; int span_id = 0; int chan_id = 0; - int t = 0; + uint32_t t = 0; uint32_t tokencnt; char *uuid = NULL; const char *token = NULL; @@ -2317,7 +2317,6 @@ static FIO_SIGNAL_CB_FUNCTION(on_r2_signal) switch_set_flag_locked(tech_pvt, TFLAG_DEAD); channel = switch_core_session_get_channel(session); switch_channel_hangup(channel, caller_data->hangup_cause); - ftdm_channel_clear_token(sigmsg->channel, switch_core_session_get_uuid(session)); switch_core_session_rwunlock(session); } } diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 9da6e1e903..f08eeaacf7 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -3969,7 +3969,9 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, v if (ftdmchan->state == FTDM_CHANNEL_STATE_CALLWAITING && (digit_char == 'D' || digit_char == 'A')) { ftdmchan->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK]++; } else { - char digit_str[2] = { digit_char, 0}; + char digit_str[2] = { 0 }; + + digit_str[0] = digit_char; if (!ftdmchan->span->sig_dtmf || (ftdmchan->span->sig_dtmf(ftdmchan, (const char*)digit_str) != FTDM_BREAK)) { ftdm_channel_queue_dtmf(ftdmchan, digit_str); diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index f31eafd42e..8ddc42c963 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -310,9 +310,7 @@ static FIO_API_FUNCTION(ftdm_libpri_api) stream->write_function(stream, ftdm_libpri_usage); goto done; } - } - - if (argc == 2) { + } else if (argc == 2) { if (!strcasecmp(argv[0], "kill")) { int span_id = atoi(argv[1]); ftdm_span_t *span = NULL; @@ -321,7 +319,8 @@ static FIO_API_FUNCTION(ftdm_libpri_api) ftdm_libpri_data_t *isdn_data = span->signal_data; if (span->start != ftdm_libpri_start) { - stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); + stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n", + __FILE__, ftdm_span_get_name(span)); goto done; } @@ -329,13 +328,12 @@ static FIO_API_FUNCTION(ftdm_libpri_api) stream->write_function(stream, "%s: +OK killed.\n", __FILE__); goto done; } else { - stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); + stream->write_function(stream, "%s: -ERR span '%s' not found.\n", + __FILE__, argv[0]); goto done; } } - } - - if (argc >= 2) { + } else if (argc >= 2) { if (!strcasecmp(argv[0], "debug")) { ftdm_span_t *span = NULL; @@ -344,7 +342,8 @@ static FIO_API_FUNCTION(ftdm_libpri_api) uint32_t flags = 0; if (span->start != ftdm_libpri_start) { - stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); + stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n", + __FILE__, ftdm_span_get_name(span)); goto done; } @@ -364,7 +363,8 @@ static FIO_API_FUNCTION(ftdm_libpri_api) stream->write_function(stream, "%s: +OK debug %s.\n", __FILE__, (flags) ? "enabled" : "disabled"); goto done; } else { - stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); + stream->write_function(stream, "%s: -ERR span '%s' not found.\n", + __FILE__, argv[0]); goto done; } } @@ -372,8 +372,10 @@ static FIO_API_FUNCTION(ftdm_libpri_api) ftdm_span_t *span = NULL; if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) { ftdm_libpri_data_t *isdn_data = span->signal_data; + if (span->start != ftdm_libpri_start) { - stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); + stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n", + __FILE__, ftdm_span_get_name(span)); goto done; } @@ -381,7 +383,8 @@ static FIO_API_FUNCTION(ftdm_libpri_api) stream->write_function(stream, "%s: +OK reset.\n", __FILE__); goto done; } else { - stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); + stream->write_function(stream, "%s: -ERR span '%s' not found.\n", + __FILE__, argv[0]); goto done; } } @@ -389,8 +392,10 @@ static FIO_API_FUNCTION(ftdm_libpri_api) ftdm_span_t *span = NULL; if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) { ftdm_libpri_data_t *isdn_data = span->signal_data; + if (span->start != ftdm_libpri_start) { - stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); + stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n", + __FILE__, ftdm_span_get_name(span)); goto done; } if (!strcasecmp(argv[2], "all")) { @@ -405,7 +410,8 @@ static FIO_API_FUNCTION(ftdm_libpri_api) stream->write_function(stream, "%s: +OK restart set.\n", __FILE__); goto done; } else { - stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); + stream->write_function(stream, "%s: -ERR span '%s' not found.\n", + __FILE__, argv[0]); goto done; } } @@ -413,8 +419,10 @@ static FIO_API_FUNCTION(ftdm_libpri_api) ftdm_span_t *span = NULL; if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) { ftdm_libpri_data_t *isdn_data = span->signal_data; + if (span->start != ftdm_libpri_start) { - stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); + stream->write_function(stream, "%s: -ERR '%s' is not a libpri span.\n", + __FILE__, ftdm_span_get_name(span)); goto done; } if (!isdn_data->service_message_support) { @@ -433,11 +441,15 @@ static FIO_API_FUNCTION(ftdm_libpri_api) stream->write_function(stream, "%s: +OK change status set.\n", __FILE__); goto done; } else { - stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); + stream->write_function(stream, "%s: -ERR span '%s' not found.\n", + __FILE__, argv[0]); goto done; } } - + } else { + /* zero args print usage */ + stream->write_function(stream, ftdm_libpri_usage); + goto done; } stream->write_function(stream, "%s: -ERR invalid command.\n", __FILE__); @@ -1165,7 +1177,7 @@ static int on_proceeding(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ if (chan) { /* Open channel if inband information is available */ - if (pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { + if (pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE || pevent->proceeding.progressmask & PRI_PROG_CALL_NOT_E2E_ISDN) { ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, B-Channel %d:%d\n", ftdm_channel_get_span_id(chan), ftdm_channel_get_id(chan)); @@ -1207,7 +1219,7 @@ static int on_progress(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev if (chan) { /* Open channel if inband information is available */ - if (pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { + if (pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE || pevent->proceeding.progressmask & PRI_PROG_CALL_NOT_E2E_ISDN) { ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, B-Channel %d:%d\n", ftdm_channel_get_span_id(chan), ftdm_channel_get_id(chan)); diff --git a/libs/freetdm/src/ftmod/ftmod_pritap/ftmod_pritap.c b/libs/freetdm/src/ftmod/ftmod_pritap/ftmod_pritap.c index 53afebc77e..29c7860220 100644 --- a/libs/freetdm/src/ftmod/ftmod_pritap/ftmod_pritap.c +++ b/libs/freetdm/src/ftmod/ftmod_pritap/ftmod_pritap.c @@ -547,7 +547,7 @@ static void handle_pri_passive_event(pritap_t *pritap, pri_event *e) break; case PRI_EVENT_PROGRESS: - crv = tap_pri_get_crv(pritap->pri, e->ring.call); + crv = tap_pri_get_crv(pritap->pri, e->proceeding.call); ftdm_log(FTDM_LOG_DEBUG, "Progress on channel %s:%d:%d with callref %d\n", pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv); break; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index c3aa964d4d..262cd9d03d 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -1155,6 +1155,77 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config) return FTDM_FAIL; } + if (span_data->cid_name_method == SNGISDN_CID_NAME_AUTO) { + switch (span_data->switchtype) { + case SNGISDN_SWITCH_EUROISDN: + if (FTDM_SPAN_IS_BRI(span)) { + span_data->cid_name_method = SNGISDN_CID_NAME_USR_USR_IE; + } else { + span_data->cid_name_method = SNGISDN_CID_NAME_DISPLAY_IE; + } + break; + case SNGISDN_SWITCH_DMS100: + span_data->cid_name_method = SNGISDN_CID_NAME_DISPLAY_IE; + break; + case SNGISDN_SWITCH_NI2: + case SNGISDN_SWITCH_5ESS: + case SNGISDN_SWITCH_4ESS: + span_data->cid_name_method = SNGISDN_CID_NAME_FACILITY_IE; + break; + default: + break; + } + } + + if (span_data->send_cid_name == SNGISDN_OPT_DEFAULT) { + switch (span_data->switchtype) { + case SNGISDN_SWITCH_EUROISDN: +#ifdef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY + case SNGISDN_SWITCH_NI2: + case SNGISDN_SWITCH_5ESS: + case SNGISDN_SWITCH_4ESS: +#endif + if (span_data->signalling == SNGISDN_SIGNALING_NET) { + span_data->send_cid_name = SNGISDN_OPT_TRUE; + } else { + span_data->send_cid_name = SNGISDN_OPT_FALSE; + } + break; + case SNGISDN_SWITCH_DMS100: + span_data->send_cid_name = SNGISDN_OPT_TRUE; + break; +#ifndef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY + case SNGISDN_SWITCH_NI2: + case SNGISDN_SWITCH_5ESS: + case SNGISDN_SWITCH_4ESS: + span_data->send_cid_name = SNGISDN_OPT_FALSE; + break; +#endif + default: + span_data->send_cid_name = SNGISDN_OPT_FALSE; + break; + } + } else if (span_data->send_cid_name == SNGISDN_OPT_TRUE) { + switch (span_data->switchtype) { + case SNGISDN_SWITCH_NI2: + case SNGISDN_SWITCH_5ESS: + case SNGISDN_SWITCH_4ESS: +#ifndef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY + ftdm_log(FTDM_LOG_WARNING, "Sending Calling Name in Facility IE not supported, please update your libsng_isdn library\n"); + span_data->send_cid_name = SNGISDN_OPT_FALSE; +#endif + break; + case SNGISDN_SWITCH_INSNET: /* Don't know how to transmit caller ID name on INSNET */ + case SNGISDN_SWITCH_QSIG: /* It seems like QSIG does not support Caller ID */ + span_data->send_cid_name = SNGISDN_OPT_FALSE; + break; + case SNGISDN_SWITCH_EUROISDN: + break; + default: + span_data->send_cid_name = SNGISDN_OPT_FALSE; + break; + } + } span->start = ftdm_sangoma_isdn_start; span->stop = ftdm_sangoma_isdn_stop; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index fee68ec41a..a095b0d57e 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -132,6 +132,13 @@ typedef enum { SNGISDN_AVAIL_UP = 10, } sngisdn_avail_t; +typedef enum { + SNGISDN_CID_NAME_AUTO, + SNGISDN_CID_NAME_DISPLAY_IE, + SNGISDN_CID_NAME_USR_USR_IE, + SNGISDN_CID_NAME_FACILITY_IE, +} sngisdn_cid_name_t; + typedef enum { SNGISDN_EVENT_CON_IND = 1, SNGISDN_EVENT_CON_CFM, @@ -262,10 +269,10 @@ typedef struct sngisdn_span_data { uint8_t raw_trace_q921; /* TODO: combine with trace_flags */ uint8_t timer_t3; uint8_t restart_opt; - uint8_t dynamic_tei; uint8_t restart_timeout; uint8_t force_sending_complete; - uint8_t cid_name_in_display_ie; /* In BRI, send the CID-name inside Display IE instead of Usr-usr */ + uint8_t cid_name_method; + uint8_t send_cid_name; char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS]; ftdm_timer_id_t timers[SNGISDN_NUM_SPAN_TIMERS]; ftdm_sched_t *sched; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c index e5928720a0..ba9226b9bc 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c @@ -284,12 +284,14 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ signal_data->ignore_cause_value = SNGISDN_OPT_DEFAULT; signal_data->timer_t3 = 8; signal_data->restart_opt = SNGISDN_OPT_DEFAULT; - signal_data->dynamic_tei = SNGISDN_OPT_DEFAULT; signal_data->link_id = span->span_id; signal_data->transfer_timeout = 20000; signal_data->att_remove_dtmf = SNGISDN_OPT_DEFAULT; signal_data->force_sending_complete = SNGISDN_OPT_DEFAULT; + signal_data->cid_name_method = SNGISDN_CID_NAME_AUTO; + signal_data->send_cid_name = SNGISDN_OPT_DEFAULT; + span->default_caller_data.dnis.plan = FTDM_NPI_INVALID; span->default_caller_data.dnis.type = FTDM_TON_INVALID; span->default_caller_data.cid_num.plan = FTDM_NPI_INVALID; @@ -362,8 +364,6 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ parse_yesno(var, val, &signal_data->restart_opt); } else if (!strcasecmp(var, "channel-restart-timeout")) { signal_data->restart_timeout = atoi(val); - } else if (!strcasecmp(var, "dynamic-tei")) { - parse_yesno(var, val, &signal_data->dynamic_tei); } else if (!strcasecmp(var, "local-number")) { if (add_local_number(val, span) != FTDM_SUCCESS) { return FTDM_FAIL; @@ -404,8 +404,30 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ #else ftdm_log(FTDM_LOG_WARNING, "chan-id-invert-extend-bit is not supported in your version of libsng_isdn\n"); #endif - } else if (!strcasecmp(var, "cid-name-in-display-ie")) { - parse_yesno(var, val, &signal_data->cid_name_in_display_ie); + } else if (!strcasecmp(var, "cid-name-transmit-method")) { + if (!strcasecmp(val, "display-ie")) { + signal_data->cid_name_method = SNGISDN_CID_NAME_DISPLAY_IE; + } else if (!strcasecmp(val, "user-user-ie")) { + signal_data->cid_name_method = SNGISDN_CID_NAME_USR_USR_IE; + } else if (!strcasecmp(val, "facility-ie")) { + signal_data->cid_name_method = SNGISDN_CID_NAME_FACILITY_IE; + } else if (!strcasecmp(val, "auto") || !strcasecmp(val, "automatic") || !strcasecmp(val, "default")) { + signal_data->cid_name_method = SNGISDN_CID_NAME_AUTO; + } else { + ftdm_log(FTDM_LOG_WARNING, "Invalid option %s for parameter %s\n", val, var); + signal_data->cid_name_method = SNGISDN_CID_NAME_AUTO; + } + } else if (!strcasecmp(var, "send-cid-name")) { + if (!strcasecmp(val, "yes")) { + signal_data->send_cid_name = SNGISDN_OPT_TRUE; + } else if (!strcasecmp(val, "no")) { + signal_data->send_cid_name = SNGISDN_OPT_FALSE; + } else if (!strcasecmp(val, "auto") || !strcasecmp(val, "automatic") || !strcasecmp(val, "default")) { + signal_data->send_cid_name = SNGISDN_OPT_DEFAULT; + } else { + ftdm_log(FTDM_LOG_WARNING, "Invalid option %s for parameter %s\n", val, var); + signal_data->send_cid_name = SNGISDN_OPT_DEFAULT; + } } else { ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var); } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c index 2b9bceea25..b121fee6cf 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c @@ -865,12 +865,6 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span) return FTDM_FAIL; } - /* Override TEI teiAlloc Option if user specified it */ - if (signal_data->dynamic_tei != SNGISDN_OPT_DEFAULT ) { - ftdm_log(FTDM_LOG_DEBUG, "%s: TEI allocation set to %s\n", span->name, (signal_data->dynamic_tei == SNGISDN_OPT_TRUE)? "dynamic": "static"); - cfg.t.cfg.s.inDLSAP.teiAlloc = (signal_data->dynamic_tei==SNGISDN_OPT_TRUE)?IN_DYNAMIC:IN_STATIC; - } - if (sng_isdn_q931_config(&pst, &cfg)) { return FTDM_FAIL; } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c index 8ae33cee0a..fe11e194b2 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c @@ -897,12 +897,19 @@ int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_l1_frame_t *l1_frame) do { flags = FTDM_WRITE; status = signal_data->dchan->fio->wait(signal_data->dchan, &flags, 1000); - if (status != FTDM_SUCCESS) { - ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_WARNING, "transmit timed-out\n"); - return -1; + switch(status) { + case FTDM_SUCCESS: + break; + case FTDM_TIMEOUT: + continue; + case FTDM_FAIL: + default: + ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_WARNING, "failed to poll for channel\n"); + return -1; } + /* status = FTDM_SUCCESS */ if ((flags & FTDM_WRITE)) { #if 0 int i; @@ -993,7 +1000,9 @@ void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...) ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s\n", data); break; case SNG_LOGLEVEL_WARN: - ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s\n", data); + if ( strncmp(data, "Invalid Q.921/Q.931 frame", 25) ) { + ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data); + } break; case SNG_LOGLEVEL_INFO: ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s\n", data); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index af2c2e95d1..70028e647d 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -567,7 +567,7 @@ ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.digits"); - if ((string == NULL) || !(*string)) { + if (ftdm_strlen_zero(string)) { return FTDM_FAIL; } @@ -696,70 +696,71 @@ ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb) ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt) { uint8_t len; - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - /* sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; */ + const char *string = NULL; + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - + ftdm_bool_t force_send_cid_name = FTDM_FALSE; + len = strlen(caller_data->cid_name); if (!len) { return FTDM_SUCCESS; } - if (FTDM_SPAN_IS_BRI(ftdmchan->span) && - signal_data->cid_name_in_display_ie != SNGISDN_OPT_TRUE) { - - conEvnt->usrUsr.eh.pres = PRSNT_NODEF; - conEvnt->usrUsr.protocolDisc.pres = PRSNT_NODEF; - conEvnt->usrUsr.protocolDisc.val = PD_IA5; /* IA5 chars */ - conEvnt->usrUsr.usrInfo.pres = PRSNT_NODEF; - conEvnt->usrUsr.usrInfo.len = len; - /* in sangoma_brid we used to send usr-usr info as !, - change to previous style if current one does not work */ - memcpy(conEvnt->usrUsr.usrInfo.val, caller_data->cid_name, len); - } else { - switch (signal_data->switchtype) { - case SNGISDN_SWITCH_NI2: -#ifdef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY - { - if (signal_data->signalling == SNGISDN_SIGNALING_NET) { - sng_isdn_encode_facility_caller_name(caller_data->cid_name, conEvnt->facilityStr.facilityStr.val, &conEvnt->facilityStr.facilityStr.len); - conEvnt->facilityStr.eh.pres = PRSNT_NODEF; - conEvnt->facilityStr.facilityStr.pres = PRSNT_NODEF; - } - } -#endif - break; - case SNGISDN_SWITCH_EUROISDN: - if (signal_data->signalling != SNGISDN_SIGNALING_NET) { - break; - } - /* follow through */ - case SNGISDN_SWITCH_5ESS: - case SNGISDN_SWITCH_4ESS: - conEvnt->display.dispInfo.pres = PRSNT_NODEF; - conEvnt->display.dispInfo.len = len; - memcpy(conEvnt->display.dispInfo.val, caller_data->cid_name, len); - break; - case SNGISDN_SWITCH_DMS100: - conEvnt->ntDisplay[0].eh.pres = PRSNT_NODEF; - conEvnt->ntDisplay[0].dispTypeNt.pres = PRSNT_NODEF; - conEvnt->ntDisplay[0].dispTypeNt.val = 0x01; /* Calling Party Name */ - conEvnt->ntDisplay[0].assocInfo.pres = PRSNT_NODEF; - conEvnt->ntDisplay[0].assocInfo.val = 0x03; /* Included */ - conEvnt->ntDisplay[0].eh.pres = PRSNT_NODEF; - conEvnt->ntDisplay[0].eh.pres = PRSNT_NODEF; - conEvnt->ntDisplay[0].dispInfo.pres = PRSNT_NODEF; - conEvnt->ntDisplay[0].dispInfo.len = len; - memcpy(conEvnt->ntDisplay[0].dispInfo.val, caller_data->cid_name, len); - break; - case SNGISDN_SWITCH_QSIG: - /* It seems like QSIG does not support Caller ID Name */ - break; - case SNGISDN_SWITCH_INSNET: - /* Don't know how to transmit caller ID name on INSNET */ - break; + string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.send_cid_name"); + if (!ftdm_strlen_zero(string)) { + if (!strcasecmp(string, "no")) { + return FTDM_SUCCESS; + } else if (!strcasecmp(string, "yes")) { + force_send_cid_name = FTDM_TRUE; } } + + if (force_send_cid_name == FTDM_FALSE && signal_data->send_cid_name == SNGISDN_OPT_FALSE) { + return FTDM_SUCCESS; + } + + switch(signal_data->cid_name_method) { + case SNGISDN_CID_NAME_FACILITY_IE: +#ifdef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY + /* Note: The Facility IE will be overwritten if user chose to transmit a Raw Facility IE */ + sng_isdn_encode_facility_caller_name(caller_data->cid_name, conEvnt->facilityStr.facilityStr.val, &conEvnt->facilityStr.facilityStr.len); + conEvnt->facilityStr.eh.pres = PRSNT_NODEF; + conEvnt->facilityStr.facilityStr.pres = PRSNT_NODEF; +#endif + break; + case SNGISDN_CID_NAME_USR_USR_IE: + conEvnt->usrUsr.eh.pres = PRSNT_NODEF; + conEvnt->usrUsr.protocolDisc.pres = PRSNT_NODEF; + conEvnt->usrUsr.protocolDisc.val = PD_IA5; /* IA5 chars */ + conEvnt->usrUsr.usrInfo.pres = PRSNT_NODEF; + conEvnt->usrUsr.usrInfo.len = len; + /* in sangoma_brid we used to send usr-usr info as !, + change to previous style if current one does not work */ + memcpy(conEvnt->usrUsr.usrInfo.val, caller_data->cid_name, len); + break; + case SNGISDN_CID_NAME_DISPLAY_IE: + if (signal_data->switchtype == SNGISDN_SWITCH_DMS100) { + conEvnt->ntDisplay[0].eh.pres = PRSNT_NODEF; + conEvnt->ntDisplay[0].dispTypeNt.pres = PRSNT_NODEF; + conEvnt->ntDisplay[0].dispTypeNt.val = 0x01; /* Calling Party Name */ + conEvnt->ntDisplay[0].assocInfo.pres = PRSNT_NODEF; + conEvnt->ntDisplay[0].assocInfo.val = 0x03; /* Included */ + conEvnt->ntDisplay[0].eh.pres = PRSNT_NODEF; + conEvnt->ntDisplay[0].eh.pres = PRSNT_NODEF; + conEvnt->ntDisplay[0].dispInfo.pres = PRSNT_NODEF; + conEvnt->ntDisplay[0].dispInfo.len = len; + memcpy(conEvnt->ntDisplay[0].dispInfo.val, caller_data->cid_name, len); + } else { + conEvnt->display.eh.pres = PRSNT_NODEF; + conEvnt->display.dispInfo.pres = PRSNT_NODEF; + conEvnt->display.dispInfo.len = len; + memcpy(conEvnt->display.dispInfo.val, caller_data->cid_name, len); + } + break; + default: + break; + } + return FTDM_SUCCESS; } @@ -767,7 +768,7 @@ ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad) { const char* clg_subaddr = NULL; clg_subaddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.calling_subaddr"); - if ((clg_subaddr != NULL) && (*clg_subaddr)) { + if (!ftdm_strlen_zero(clg_subaddr)) { unsigned len = strlen (clg_subaddr); cgPtySad->eh.pres = PRSNT_NODEF; cgPtySad->typeSad.pres = 1; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c index acb29ba385..4333f02887 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c @@ -62,6 +62,7 @@ sng_switch_type_t sng_switch_type_map[] = { 1, "india" , LSI_SW_INDIA , LSI_SW_INDIA }, { 1, "uk" , LSI_SW_UK , LSI_SW_UK }, { 1, "russia" , LSI_SW_RUSSIA , LSI_SW_RUSSIA }, + { 1, "china" , LSI_SW_CHINA , LSI_SW_CHINA }, { 0, "", 0, 0 }, }; diff --git a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c index 4e7914685b..677bcbbd56 100644 --- a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c +++ b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c @@ -256,7 +256,7 @@ static void zt_build_gains(struct zt_gains *g, float rxgain, float txgain, int c } /** - * \brief Initialises a range of ftdmtel channels + * \brief Initialises a range of Zaptel/DAHDI channels * \param span FreeTDM span * \param start Initial wanpipe channel number * \param end Final wanpipe channel number @@ -349,7 +349,7 @@ static unsigned zt_open_range(ftdm_span_t *span, unsigned start, unsigned end, f } if (ioctl(CONTROL_FD, codes.CHANCONFIG, &cc)) { - ftdm_log(FTDM_LOG_WARNING, "this ioctl fails on older ftdmtel but is harmless if you used ztcfg\n[device %s chan %d fd %d (%s)]\n", chanpath, x, CONTROL_FD, strerror(errno)); + ftdm_log(FTDM_LOG_WARNING, "this ioctl fails in older zaptel but is harmless if you used ztcfg\n[device %s chan %d fd %d (%s)]\n", chanpath, x, CONTROL_FD, strerror(errno)); } } @@ -453,7 +453,7 @@ static unsigned zt_open_range(ftdm_span_t *span, unsigned start, unsigned end, f } /** - * \brief Initialises an freetdm ftdmtel span from a configuration string + * \brief Initialises a freetdm Zaptel/DAHDI span from a configuration string * \param span FreeTDM span * \param str Configuration string * \param type FreeTDM span type @@ -523,7 +523,7 @@ static FIO_CONFIGURE_SPAN_FUNCTION(zt_configure_span) } /** - * \brief Process configuration variable for a ftdmtel profile + * \brief Process configuration variable for a Zaptel/DAHDI profile * \param category Wanpipe profile name * \param var Variable name * \param val Variable value @@ -601,7 +601,7 @@ static FIO_CONFIGURE_FUNCTION(zt_configure) } /** - * \brief Opens a ftdmtel channel + * \brief Opens a Zaptel/DAHDI channel * \param ftdmchan Channel to open * \return Success or failure */ @@ -671,7 +671,7 @@ static FIO_OPEN_FUNCTION(zt_open) } /** - * \brief Closes ftdmtel channel + * \brief Closes Zaptel/DAHDI channel * \param ftdmchan Channel to close * \return Success */ @@ -689,7 +689,7 @@ static FIO_CLOSE_FUNCTION(zt_close) } /** - * \brief Executes an FreeTDM command on a ftdmtel channel + * \brief Executes a FreeTDM command on a Zaptel/DAHDI channel * \param ftdmchan Channel to execute command on * \param command FreeTDM command to execute * \param obj Object (unused) @@ -870,7 +870,7 @@ static FIO_COMMAND_FUNCTION(zt_command) } /** - * \brief Gets alarms from a ftdmtel Channel + * \brief Gets alarms from a Zaptel/DAHDI channel * \param ftdmchan Channel to get alarms from * \return Success or failure */ @@ -893,7 +893,7 @@ static FIO_GET_ALARMS_FUNCTION(zt_get_alarms) } /** - * \brief Waits for an event on a ftdmtel channel + * \brief Waits for an event on a Zaptel/DAHDI channel * \param ftdmchan Channel to open * \param flags Type of event to wait for * \param to Time to wait (in ms) @@ -967,7 +967,7 @@ pollagain: } /** - * \brief Checks for events on a ftdmtel span + * \brief Checks for events on a Zaptel/DAHDI span * \param span Span to check for events * \param ms Time to wait for event * \return Success if event is waiting or failure if not @@ -1164,7 +1164,7 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(zt_channel_next_event) } /** - * \brief Retrieves an event from a ftdmtel span + * \brief Retrieves an event from a Zaptel/DAHDI span * \param span Span to retrieve event from * \param event FreeTDM event to return * \return Success or failure @@ -1204,7 +1204,7 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event) } /** - * \brief Reads data from a ftdmtel channel + * \brief Reads data from a Zaptel/DAHDI channel * \param ftdmchan Channel to read from * \param data Data buffer * \param datalen Size of data buffer @@ -1246,7 +1246,7 @@ static FIO_READ_FUNCTION(zt_read) } /** - * \brief Writes data to a ftdmtel channel + * \brief Writes data to a Zaptel/DAHDI channel * \param ftdmchan Channel to write to * \param data Data buffer * \param datalen Size of data buffer @@ -1285,7 +1285,7 @@ tryagain: } /** - * \brief Destroys a ftdmtel Channel + * \brief Destroys a Zaptel/DAHDI Channel * \param ftdmchan Channel to destroy * \return Success */ @@ -1298,12 +1298,12 @@ static FIO_CHANNEL_DESTROY_FUNCTION(zt_channel_destroy) } /** - * \brief Global FreeTDM IO interface for ftdmtel + * \brief Global FreeTDM IO interface for Zaptel/DAHDI */ static ftdm_io_interface_t zt_interface; /** - * \brief Loads ftdmtel IO module + * \brief Loads Zaptel/DAHDI IO module * \param fio FreeTDM IO interface * \return Success or failure */ @@ -1358,7 +1358,7 @@ static FIO_IO_LOAD_FUNCTION(zt_init) } /** - * \brief Unloads ftdmtel IO module + * \brief Unloads Zaptel/DAHDI IO module * \return Success */ static FIO_IO_UNLOAD_FUNCTION(zt_destroy) @@ -1369,7 +1369,7 @@ static FIO_IO_UNLOAD_FUNCTION(zt_destroy) } /** - * \brief FreeTDM ftdmtel IO module definition + * \brief FreeTDM Zaptel/DAHDI IO module definition */ ftdm_module_t ftdm_module = { "zt", diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 9c5c9ad468..65ffad677c 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -104,6 +104,10 @@ #include #endif +#ifdef __linux__ +#include +#endif + #include #include #include @@ -220,6 +224,27 @@ extern "C" { #define ftdm_is_dtmf(key) ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119) +#ifdef __linux__ +#define ftdm_print_stack(level) \ + do { \ + void *__stacktrace[100] = { 0 }; \ + char **__symbols = NULL; \ + int __size = 0; \ + int __i = 0; \ + __size = backtrace(__stacktrace, ftdm_array_len(__stacktrace)); \ + __symbols = backtrace_symbols(__stacktrace, __size); \ + if (__symbols) { \ + for (__i = 0; __i < __size; __i++) { \ + ftdm_log(__level, "%s\n", __symbols[i]); \ + } \ + free(__symbols); \ + } \ + } while (0); +#else +#define ftdm_print_stack(level) ftdm_log(level, "FTDM_PRINT_STACK is not implemented in this operating system!\n"); +#endif + + #define FTDM_SPAN_IS_BRI(x) ((x)->trunk_type == FTDM_TRUNK_BRI || (x)->trunk_type == FTDM_TRUNK_BRI_PTMP) /*! \brief Copy flags from one arbitrary object to another diff --git a/libs/iksemel/INSTALL b/libs/iksemel/INSTALL index 23e5f25d0e..7d1c323bea 100644 --- a/libs/iksemel/INSTALL +++ b/libs/iksemel/INSTALL @@ -1,16 +1,25 @@ Installation Instructions ************************* -Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free -Software Foundation, Inc. +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, +2006, 2007, 2008, 2009 Free Software Foundation, Inc. -This file is free documentation; the Free Software Foundation gives -unlimited permission to copy, distribute and modify it. + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. Basic Installation ================== -These are generic installation instructions. + Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. Some packages provide this +`INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses @@ -23,9 +32,9 @@ debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. (Caching is +the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale -cache files.) +cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail @@ -35,30 +44,37 @@ some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You only need -`configure.ac' if you want to change it or regenerate `configure' using -a newer version of `autoconf'. +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. -The simplest way to compile this package is: + The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. If you're - using `csh' on an old version of System V, you might need to type - `sh ./configure' instead to prevent `csh' from trying to execute - `configure' itself. + `./configure' to configure the package for your system. - Running `configure' takes awhile. While running, it prints some - messages telling which features it is checking for. + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with - the package. + the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and - documentation. + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the `make install' phase executed with root + privileges. - 5. You can remove the program binaries and object files from the + 5. Optionally, type `make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior `make install' required + root privileges, verifies that the installation completed + correctly. + + 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is @@ -67,45 +83,69 @@ The simplest way to compile this package is: all sorts of other programs in order to regenerate files that came with the distribution. + 7. Often, you can also type `make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide `make + distcheck', which can by used by developers to test that all other + targets like `make install' and `make uninstall' work correctly. + This target is generally not run by end users. + Compilers and Options ===================== -Some systems require unusual options for compilation or linking that the -`configure' script does not know about. Run `./configure --help' for -details on some of the pertinent environment variables. + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: - ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== -You can compile the package for more than one kind of computer at the + You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their -own directory. To do this, you must use a version of `make' that -supports the `VPATH' variable, such as GNU `make'. `cd' to the +own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. +source code in the directory that `configure' is in and in `..'. This +is known as a "VPATH" build. - If you have to use a `make' that does not support the `VPATH' -variable, you have to compile the package for one architecture at a -time in the source code directory. After you have installed the -package for one architecture, use `make distclean' before reconfiguring -for another architecture. + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple `-arch' options to the +compiler but only a single `-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the `lipo' tool if you have problems. Installation Names ================== -By default, `make install' installs the package's commands under + By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving -`configure' the option `--prefix=PREFIX'. +`configure' the option `--prefix=PREFIX', where PREFIX must be an +absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you @@ -116,16 +156,47 @@ Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. +you can set and what kinds of files go in them. In general, the +default for these options is expressed in terms of `${prefix}', so that +specifying just `--prefix' will affect all of the other directory +specifications that were not explicitly provided. + + The most portable way to affect installation locations is to pass the +correct locations to `configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +`make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, `make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +`${prefix}'. Any directories that were specified during `configure', +but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of +makefile variable overrides for each directory variable is required by +the GNU Coding Standards, and ideally causes no recompilation. +However, some platforms have known limitations with the semantics of +shared libraries that end up requiring recompilation when using this +method, particularly noticeable in packages that use GNU Libtool. + + The second method involves providing the `DESTDIR' variable. For +example, `make install DESTDIR=/alternate/directory' will prepend +`/alternate/directory' before all installation names. The approach of +`DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of `${prefix}' +at `configure' time. + +Optional Features +================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. -Optional Features -================= - -Some packages pay attention to `--enable-FEATURE' options to + Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The @@ -137,14 +208,53 @@ find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. + Some packages offer the ability to configure how verbose the +execution of `make' will be. For these packages, running `./configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with `make V=1'; while running `./configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with `make V=0'. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU +CC is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its `' header file. The option `-nodtk' can be used as +a workaround. If GNU CC is not installed, it is therefore recommended +to try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + + On Solaris, don't put `/usr/ucb' early in your `PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in `/usr/bin'. So, if you need `/usr/ucb' +in your `PATH', put it _after_ `/usr/bin'. + + On Haiku, software installed for all users goes in `/boot/common', +not `/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + Specifying the System Type ========================== -There may be some features `configure' cannot figure out automatically, -but needs to determine by the type of machine the package will run on. -Usually, assuming the package is built to be run on the _same_ -architectures, `configure' can figure that out, but if it prints a -message saying it cannot guess the machine type, give it the + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: @@ -152,7 +262,8 @@ type, such as `sun4', or a canonical name which has the form: where SYSTEM can have one of these forms: - OS KERNEL-OS + OS + KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't @@ -170,9 +281,9 @@ eventually be run) with `--host=TYPE'. Sharing Defaults ================ -If you want to set default values for `configure' scripts to share, you -can create a site shell script called `config.site' that gives default -values for variables like `CC', `cache_file', and `prefix'. + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. @@ -181,7 +292,7 @@ A warning: not all `configure' scripts look for a site script. Defining Variables ================== -Variables not defined in a site shell script can be set in the + Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set @@ -190,21 +301,29 @@ them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is -overridden in the site shell script). Here is a another example: +overridden in the site shell script). - /bin/bash ./configure CONFIG_SHELL=/bin/bash +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: -Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent -configuration-related scripts to be executed by `/bin/bash'. + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== -`configure' recognizes the following options to control how it operates. + `configure' recognizes the following options to control how it +operates. `--help' `-h' - Print a summary of the options to `configure', and exit. + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. `--version' `-V' @@ -231,6 +350,16 @@ configuration-related scripts to be executed by `/bin/bash'. Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. +`--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. diff --git a/libs/iksemel/configure.ac b/libs/iksemel/configure.ac index 403725a80d..4d6ab91eb8 100644 --- a/libs/iksemel/configure.ac +++ b/libs/iksemel/configure.ac @@ -50,7 +50,10 @@ AC_SEARCH_LIBS(recv,socket) AC_CHECK_FUNCS(getopt_long) AC_CHECK_FUNCS(getaddrinfo) -AX_PATH_LIBGNUTLS(,AC_DEFINE(HAVE_GNUTLS,,"Use libgnutls")) +#AX_PATH_LIBGNUTLS(,AC_DEFINE(HAVE_GNUTLS,,"Use libgnutls")) + +m4_include([openssl.m4]) +SAC_OPENSSL dnl Check -Wall flag of GCC if test "x$GCC" = "xyes"; then diff --git a/libs/iksemel/openssl.m4 b/libs/iksemel/openssl.m4 new file mode 100644 index 0000000000..8adea2192e --- /dev/null +++ b/libs/iksemel/openssl.m4 @@ -0,0 +1,49 @@ +dnl ====================================================================== +dnl SAC_OPENSSL +dnl ====================================================================== +AC_DEFUN([SAC_OPENSSL], [ + +AC_ARG_WITH(openssl, +[ --with-openssl use OpenSSL [[enabled]]],, with_openssl=pkg-config) + +dnl SOSXXX:SAC_ASSERT_DEF([openssl libraries]) + + +if test "$with_openssl" = no ;then + : # No openssl +else + + if test "$with_openssl" = "pkg-config" ; then + PKG_CHECK_MODULES(openssl, openssl, + [HAVE_TLS=1 HAVE_SSL=1 LIBS="$openssl_LIBS $LIBS"], + [HAVE_SSL=0]) + fi + + if test x$HAVE_SSL = x1 ; then + AC_DEFINE([HAVE_LIBCRYPTO], 1, [Define to 1 if you have the `crypto' library (-lcrypto).]) + AC_DEFINE([HAVE_LIBSSL], 1, [Define to 1 if you have the `ssl' library (-lssl).]) + else + AC_CHECK_HEADERS([openssl/tls1.h], [ + HAVE_SSL=1 HAVE_TLS=1 + + AC_CHECK_LIB(crypto, BIO_new,, + HAVE_SSL=0 + AC_MSG_WARN(OpenSSL crypto library was not found)) + + AC_CHECK_LIB(ssl, TLSv1_method,, + HAVE_TLS=0 + AC_MSG_WARN(OpenSSL protocol library was not found)) + ],[AC_MSG_WARN(OpenSSL include files were not found)]) + fi + + if test x$HAVE_SSL = x1; then + AC_DEFINE([HAVE_SSL], 1, [Define to 1 if you have OpenSSL]) + fi + + if test x$HAVE_TLS = x1; then + AC_DEFINE([HAVE_TLS], 1, [Define to 1 if you have TLS]) + fi +fi + +AM_CONDITIONAL(HAVE_TLS, test x$HAVE_TLS = x1) +]) diff --git a/libs/iksemel/src/stream.c b/libs/iksemel/src/stream.c index a7e57cb236..a1a4494e59 100644 --- a/libs/iksemel/src/stream.c +++ b/libs/iksemel/src/stream.c @@ -19,6 +19,19 @@ #include #endif +#ifdef HAVE_SSL +#include +#include +#ifdef WIN32 +typedef unsigned __int32 uint32_t; +#else +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#include +#endif +#endif + #define SF_FOREIGN 1 #define SF_TRY_SECURE 2 #define SF_SECURE 4 @@ -41,9 +54,63 @@ struct stream_data { #ifdef HAVE_GNUTLS gnutls_session sess; gnutls_certificate_credentials cred; +#elif HAVE_SSL + SSL* ssl; + SSL_CTX* ssl_ctx; #endif }; +#ifdef HAVE_SSL +#ifdef WIN32 +static int sock_read_ready(struct stream_data *data, uint32_t ms) +{ + int r = 0; + fd_set fds; + struct timeval tv; + + FD_ZERO(&fds); + +#ifdef WIN32 +#pragma warning( push ) +#pragma warning( disable : 4127 ) + FD_SET(SSL_get_fd(data->ssl), &fds); +#pragma warning( pop ) +#else + FD_SET(SSL_get_fd(data->ssl), &fds); +#endif + + tv.tv_sec = ms / 1000; + tv.tv_usec = (ms % 1000) * ms; + + r = select (SSL_get_fd(data->ssl) + 1, &fds, NULL, NULL, &tv); + + return r; +} +#else +static int sock_read_ready(struct stream_data *data, int ms) +{ + struct pollfd pfds[2] = { { 0 } }; + int s = 0, r = 0; + + pfds[0].fd = SSL_get_fd(data->ssl); + pfds[0].events |= POLLIN; + + s = poll(pfds, 1, ms); + + + if (s < 0) { + r = s; + } else if (s > 0) { + if ((pfds[0].revents & POLLIN)) { + r = 1; + } + } + + return r; +} +#endif +#endif + #ifdef HAVE_GNUTLS #ifndef WIN32 #include @@ -120,6 +187,86 @@ handshake (struct stream_data *data) iks_send_header (data->prs, data->server); return IKS_OK; +} // HAVE_GNUTLS +#elif HAVE_SSL +static int wait_for_data(struct stream_data *data, int ret, int timeout) +{ + struct timeval tv; + fd_set fds; + int err; + int retval = IKS_OK; + + err = SSL_get_error(data->ssl, ret); + + switch(err) + { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + ret = sock_read_ready(data, timeout*1000); + + if (ret == -1) { + retval = IKS_NET_TLSFAIL; + } + + break; + default: + if(data->logHook) + data->logHook(data->user_data, ERR_error_string(err, NULL), strlen(ERR_error_string(err, NULL)), 1); + retval = IKS_NET_TLSFAIL; + break; + } + + ERR_clear_error(); + + return retval; +} + +static int +handshake (struct stream_data *data) +{ + int ret; + int finished; + + SSL_library_init(); + SSL_load_error_strings(); + + data->ssl_ctx = SSL_CTX_new(TLSv1_method()); + if(!data->ssl_ctx) return IKS_NOMEM; + + data->ssl = SSL_new(data->ssl_ctx); + if(!data->ssl) return IKS_NOMEM; + + if( SSL_set_fd(data->ssl, (int)data->sock) != 1 ) return IKS_NOMEM; + + /* Set both the read and write BIO's to non-blocking mode */ + BIO_set_nbio(SSL_get_rbio(data->ssl), 1); + BIO_set_nbio(SSL_get_wbio(data->ssl), 1); + + finished = 0; + + do + { + ret = SSL_connect(data->ssl); + + if( ret != 1 ) + { + if( wait_for_data(data, ret, 1) != IKS_OK ) + { + finished = 1; + SSL_free(data->ssl); + } + } + } while( ret != 1 && finished != 1 ); + + if( ret == 1 ) + { + data->flags &= (~SF_TRY_SECURE); + data->flags |= SF_SECURE; + + iks_send_header (data->prs, data->server); + } + + return ret == 1 ? IKS_OK : IKS_NET_TLSFAIL; } #endif @@ -295,6 +442,15 @@ tagHook (struct stream_data *data, char *name, char **atts, int type) return IKS_NET_TLSFAIL; } } +#elif HAVE_SSL + if (data->flags & SF_TRY_SECURE) { + if (strcmp (name, "proceed") == 0) { + err = handshake (data); + return err; + } else if (strcmp (name, "failure") == 0){ + return IKS_NET_TLSFAIL; + } + } #endif if (data->current) { x = iks_insert (data->current, name); @@ -351,6 +507,11 @@ deleteHook (struct stream_data *data) gnutls_deinit (data->sess); gnutls_certificate_free_credentials (data->cred); } +#elif HAVE_SSL + if (data->flags & SF_SECURE) { + if( SSL_shutdown(data->ssl) == 0 ) SSL_shutdown(data->ssl); + SSL_free(data->ssl); + } #endif if (data->trans) data->trans->close (data->sock); data->trans = NULL; @@ -507,6 +668,12 @@ iks_recv (iksparser *prs, int timeout) { struct stream_data *data = iks_user_data (prs); int len, ret; + +#ifdef HAVE_SSL + int err; + struct timeval tv; + fd_set fds; +#endif while (1) { #ifdef HAVE_GNUTLS @@ -514,6 +681,34 @@ iks_recv (iksparser *prs, int timeout) len = gnutls_record_recv (data->sess, data->buf, NET_IO_BUF_SIZE - 1); if (len == 0) len = -1; } else +#elif HAVE_SSL + if (data->flags & SF_SECURE) { + ret = sock_read_ready(data, timeout*1000); + + if (ret == -1) { + return IKS_NET_TLSFAIL; + } else if( ret == 0 ) { + return IKS_OK; + } else { + len = SSL_read(data->ssl, data->buf, NET_IO_BUF_SIZE - 1); + } + + if( len <= 0 ) + { + switch( err = SSL_get_error(data->ssl, len) ) + { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + return IKS_OK; + break; + default: + if(data->logHook) + data->logHook(data->user_data, ERR_error_string(err, NULL), strlen(ERR_error_string(err, NULL)), 1); + return IKS_NET_TLSFAIL; + break; + } + } + } else #endif { len = data->trans->recv (data->sock, data->buf, NET_IO_BUF_SIZE - 1, timeout); @@ -523,6 +718,7 @@ iks_recv (iksparser *prs, int timeout) data->buf[len] = '\0'; if (data->logHook) data->logHook (data->user_data, data->buf, len, 1); ret = iks_parse (prs, data->buf, len, 0); + if (ret != IKS_OK) return ret; if (!data->trans) { /* stream hook called iks_disconnect */ @@ -569,6 +765,10 @@ iks_send_raw (iksparser *prs, const char *xmlstr) if (data->flags & SF_SECURE) { if (gnutls_record_send (data->sess, xmlstr, strlen (xmlstr)) < 0) return IKS_NET_RWERR; } else +#elif HAVE_SSL + if (data->flags & SF_SECURE) { + if (SSL_write(data->ssl, xmlstr, strlen (xmlstr)) < 0) return IKS_NET_RWERR; + } else #endif { ret = data->trans->send (data->sock, xmlstr, strlen (xmlstr)); @@ -591,6 +791,8 @@ iks_has_tls (void) { #ifdef HAVE_GNUTLS return 1; +#elif HAVE_SSL + return 1; #else return 0; #endif @@ -602,6 +804,10 @@ iks_is_secure (iksparser *prs) #ifdef HAVE_GNUTLS struct stream_data *data = iks_user_data (prs); + return data->flags & SF_SECURE; +#elif HAVE_SSL + struct stream_data *data = iks_user_data (prs); + return data->flags & SF_SECURE; #else return 0; @@ -641,6 +847,14 @@ iks_start_tls (iksparser *prs) int ret; struct stream_data *data = iks_user_data (prs); + ret = iks_send_raw (prs, ""); + if (ret) return ret; + data->flags |= SF_TRY_SECURE; + return IKS_OK; +#elif HAVE_SSL + int ret; + struct stream_data *data = iks_user_data (prs); + ret = iks_send_raw (prs, ""); if (ret) return ret; data->flags |= SF_TRY_SECURE; diff --git a/libs/ldns/install-sh b/libs/ldns/install-sh index 3f83ce9b55..6781b987bd 100755 --- a/libs/ldns/install-sh +++ b/libs/ldns/install-sh @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2010-02-06.18; # UTC +scriptversion=2009-04-28.21; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -200,11 +200,7 @@ if test $# -eq 0; then fi if test -z "$dir_arg"; then - do_exit='(exit $ret); exit $ret' - trap "ret=129; $do_exit" 1 - trap "ret=130; $do_exit" 2 - trap "ret=141; $do_exit" 13 - trap "ret=143; $do_exit" 15 + trap '(exit $?); exit' 1 2 13 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. diff --git a/libs/libcodec2/Makefile.am b/libs/libcodec2/Makefile.am index a1820f9162..085b8a5b1e 100644 --- a/libs/libcodec2/Makefile.am +++ b/libs/libcodec2/Makefile.am @@ -1,5 +1,5 @@ AM_CFLAGS = -Isrc -Wall -lm -AUTOMAKE_OPTS = gnu +AUTOMAKE_OPTIONS = gnu NAME = libcodec2 AM_CPPFLAGS = $(AM_CFLAGS) diff --git a/libs/libcodec2/src/Makefile.am b/libs/libcodec2/src/Makefile.am index ce240785d9..e9b2fbc341 100644 --- a/libs/libcodec2/src/Makefile.am +++ b/libs/libcodec2/src/Makefile.am @@ -1,5 +1,5 @@ AM_CFLAGS = -I../src -Wall -DFLOATING_POINT -DVAR_ARRAYS -AUTOMAKE_OPTS = gnu +AUTOMAKE_OPTIONS = gnu NAME = libcodec2 AM_CPPFLAGS = $(AM_CFLAGS) diff --git a/libs/libcodec2/unittest/Makefile.am b/libs/libcodec2/unittest/Makefile.am index 81d546307b..e18b44d5e4 100644 --- a/libs/libcodec2/unittest/Makefile.am +++ b/libs/libcodec2/unittest/Makefile.am @@ -1,5 +1,5 @@ AM_CFLAGS = -I../src -g -DFLOATING_POINT -DVAR_ARRAYS -AUTOMAKE_OPTS = gnu +AUTOMAKE_OPTIONS = gnu NAME = libcodec2 AM_CPPFLAGS = $(AM_CFLAGS) diff --git a/libs/libdingaling/Makefile.am b/libs/libdingaling/Makefile.am index 0ca8d7a6b6..37bf42cb31 100644 --- a/libs/libdingaling/Makefile.am +++ b/libs/libdingaling/Makefile.am @@ -1,6 +1,6 @@ EXTRA_DIST = SUBDIRS = -AUTOMAKE_OPTS=foreign +AUTOMAKE_OPTIONS = foreign NAME=dingaling PREFIX=$(prefix) TOUCH_TARGET=@if test -f "$@" ; then touch "$@" ; fi ; diff --git a/libs/libdingaling/src/libdingaling.c b/libs/libdingaling/src/libdingaling.c index dbe542dc4a..9394a600d9 100644 --- a/libs/libdingaling/src/libdingaling.c +++ b/libs/libdingaling/src/libdingaling.c @@ -606,7 +606,7 @@ static int on_disco_default(void *user_data, ikspak *pak) if ((iq = iks_new("iq"))) { int all = 0; - iks_insert_attrib(iq, "from", handle->login); + iks_insert_attrib(iq, "from", iks_find_attrib(pak->x, "to")); if (pak->from) { iks_insert_attrib(iq, "to", pak->from->full); } @@ -1431,12 +1431,14 @@ static void j_setup_filter(ldl_handle_t *handle) } } -static void ldl_flush_queue(ldl_handle_t *handle, int done) +static ldl_queue_t ldl_flush_queue(ldl_handle_t *handle, int done) { iks *msg; void *pop = NULL; unsigned int len = 0, x = 0; + ldl_queue_t sent_data = LDL_QUEUE_NONE; + apr_thread_mutex_lock(handle->lock); while(apr_queue_trypop(handle->queue, &pop) == APR_SUCCESS) { @@ -1445,6 +1447,7 @@ static void ldl_flush_queue(ldl_handle_t *handle, int done) if (!done) iks_send(handle->parser, msg); iks_delete(msg); pop = NULL; + sent_data = LDL_QUEUE_SENT; } else { break; } @@ -1473,6 +1476,7 @@ static void ldl_flush_queue(ldl_handle_t *handle, int done) } iks_send(handle->parser, packet_node->xml); packet_node->next = now + 5000000; + sent_data = LDL_QUEUE_SENT; } } if (packet_node->retries == 0 || done) { @@ -1490,51 +1494,15 @@ static void ldl_flush_queue(ldl_handle_t *handle, int done) } } apr_thread_mutex_unlock(handle->lock); -} - - -static void *APR_THREAD_FUNC queue_thread(apr_thread_t *thread, void *obj) -{ - ldl_handle_t *handle = (ldl_handle_t *) obj; - - ldl_set_flag_locked(handle, LDL_FLAG_QUEUE_RUNNING); - - while (ldl_test_flag(handle, LDL_FLAG_RUNNING) && !ldl_test_flag(handle, LDL_FLAG_QUEUE_STOP)) { - ldl_flush_queue(handle, 0); - - if (handle->loop_callback(handle) != LDL_STATUS_SUCCESS || !ldl_test_flag((&globals), LDL_FLAG_READY)) { - int fd; - - if ((fd = iks_fd(handle->parser)) > -1) { - shutdown(fd, 0x02); - } - ldl_set_flag_locked(handle, LDL_FLAG_BREAK); - break; - } - microsleep(100); - } - - ldl_clear_flag_locked(handle, LDL_FLAG_QUEUE_RUNNING); - ldl_clear_flag_locked(handle, LDL_FLAG_QUEUE_STOP); - - return NULL; -} - -static void launch_queue_thread(ldl_handle_t *handle) -{ - apr_thread_t *thread; - apr_threadattr_t *thd_attr;; - apr_threadattr_create(&thd_attr, handle->pool); - apr_threadattr_detach_set(thd_attr, 1); - - apr_threadattr_stacksize_set(thd_attr, 512 * 1024); - apr_thread_create(&thread, thd_attr, queue_thread, handle, handle->pool); - + return sent_data; } static void xmpp_connect(ldl_handle_t *handle, char *jabber_id, char *pass) { + int timeout_ka = LDL_KEEPALIVE_TIMEOUT; + int count_ka = timeout_ka; + while (ldl_test_flag((&globals), LDL_FLAG_READY) && ldl_test_flag(handle, LDL_FLAG_RUNNING)) { int e; char tmp[512], *sl; @@ -1587,13 +1555,18 @@ static void xmpp_connect(ldl_handle_t *handle, char *jabber_id, char *pass) } handle->counter = opt_timeout; - if (ldl_test_flag(handle, LDL_FLAG_TLS)) { - launch_queue_thread(handle); - } while (ldl_test_flag((&globals), LDL_FLAG_READY) && ldl_test_flag(handle, LDL_FLAG_RUNNING)) { e = iks_recv(handle->parser, 1); - if (!ldl_test_flag(handle, LDL_FLAG_TLS) && handle->loop_callback) { + + if (count_ka-- <= 0) { + if( iks_send_raw(handle->parser, " ") == IKS_OK) { + count_ka = timeout_ka; + globals.logger(DL_LOG_DEBUG, "Sent keep alive signal\n"); + } + } + + if (handle->loop_callback) { if (handle->loop_callback(handle) != LDL_STATUS_SUCCESS) { ldl_clear_flag_locked(handle, LDL_FLAG_RUNNING); break; @@ -1614,10 +1587,11 @@ static void xmpp_connect(ldl_handle_t *handle, char *jabber_id, char *pass) goto fail; } - if (!ldl_test_flag(handle, LDL_FLAG_TLS) && ldl_test_flag(handle, LDL_FLAG_RUNNING)) { + if (ldl_test_flag(handle, LDL_FLAG_RUNNING)) { ldl_flush_queue(handle, 0); } + handle->counter--; if (!ldl_test_flag(handle, LDL_FLAG_CONNECTED)) { if (IKS_NET_TLSFAIL == e) { globals.logger(DL_LOG_DEBUG, "tls handshake failed\n"); @@ -1631,11 +1605,12 @@ static void xmpp_connect(ldl_handle_t *handle, char *jabber_id, char *pass) break; } } + + microsleep(100); } fail: - ldl_set_flag_locked(handle, LDL_FLAG_QUEUE_STOP); ldl_clear_flag_locked(handle, LDL_FLAG_CONNECTED); ldl_clear_flag_locked(handle, LDL_FLAG_AUTHORIZED); ldl_clear_flag_locked(handle, LDL_FLAG_BREAK); @@ -1645,23 +1620,12 @@ static void xmpp_connect(ldl_handle_t *handle, char *jabber_id, char *pass) shutdown(fd, 0x02); } - - - while(ldl_test_flag(handle, LDL_FLAG_QUEUE_RUNNING)) { - microsleep(100); - } - iks_disconnect(handle->parser); iks_parser_delete(handle->parser); } ldl_clear_flag_locked(handle, LDL_FLAG_RUNNING); - if (!ldl_test_flag(handle, LDL_FLAG_TLS)) { - ldl_flush_queue(handle, 1); - } - while(ldl_test_flag(handle, LDL_FLAG_QUEUE_RUNNING)) { - microsleep(100); - } + ldl_flush_queue(handle, 1); ldl_set_flag_locked(handle, LDL_FLAG_STOPPED); @@ -2512,13 +2476,15 @@ int ldl_handle_authorized(ldl_handle_t *handle) void ldl_handle_stop(ldl_handle_t *handle) { ldl_clear_flag_locked(handle, LDL_FLAG_RUNNING); +#if 0 if (ldl_test_flag(handle, LDL_FLAG_TLS)) { int fd; if ((fd = iks_fd(handle->parser)) > -1) { shutdown(fd, 0x02); } } - +#endif + while(!ldl_test_flag(handle, LDL_FLAG_STOPPED)) { microsleep(100); } diff --git a/libs/libdingaling/src/libdingaling.h b/libs/libdingaling/src/libdingaling.h index f103327339..28cc919e6b 100644 --- a/libs/libdingaling/src/libdingaling.h +++ b/libs/libdingaling/src/libdingaling.h @@ -64,6 +64,8 @@ extern "C" { #define LDL_MAX_PAYLOADS 50 #define LDL_RETRY 3 #define IKS_NS_COMPONENT "jabber:component:accept" +/* period between keep alive signals in 0.1sec units*/ +#define LDL_KEEPALIVE_TIMEOUT 6000 /*! \brief A structure to store a jingle candidate */ struct ldl_candidate { @@ -119,10 +121,8 @@ typedef enum { LDL_FLAG_AUTHORIZED = (1 << 2), LDL_FLAG_READY = (1 << 3), LDL_FLAG_CONNECTED = (1 << 4), - LDL_FLAG_QUEUE_RUNNING = (1 << 5), - LDL_FLAG_STOPPED = (1 << 6), - LDL_FLAG_QUEUE_STOP = (1 << 7), - LDL_FLAG_BREAK = (1 << 8) + LDL_FLAG_STOPPED = (1 << 5), + LDL_FLAG_BREAK = (1 << 6) } ldl_flag_t; typedef enum { @@ -173,6 +173,11 @@ typedef enum { LDL_DESCRIPTION_ACCEPT } ldl_description_t; +typedef enum { + LDL_QUEUE_NONE, + LDL_QUEUE_SENT +} ldl_queue_t; + #define DL_PRE __FILE__, __LDL_FUNC__, __LINE__ #define DL_LOG_DEBUG DL_PRE, 7 #define DL_LOG_INFO DL_PRE, 6 diff --git a/libs/libteletone/Makefile.am b/libs/libteletone/Makefile.am index 6175c2fa33..7fd489c721 100644 --- a/libs/libteletone/Makefile.am +++ b/libs/libteletone/Makefile.am @@ -1,6 +1,6 @@ EXTRA_DIST = SUBDIRS = -AUTOMAKE_OPTS= gnu +AUTOMAKE_OPTIONS = gnu NAME=teletone AM_CFLAGS = $(new_AM_CFLAGS) -I./src diff --git a/libs/pcre/pcre_ucp_searchfuncs.c b/libs/pcre/pcre_ucp_searchfuncs.c index a9df1f0d31..83ee7ff5a6 100644 --- a/libs/pcre/pcre_ucp_searchfuncs.c +++ b/libs/pcre/pcre_ucp_searchfuncs.c @@ -155,12 +155,12 @@ for (;;) if (top <= bot) return -1; mid = (bot + top) >> 1; if (c == (ucp_table[mid].f0 & f0_charmask)) break; - if (c < (ucp_table[mid].f0 & f0_charmask)) top = mid; + if (c < (int)(ucp_table[mid].f0 & f0_charmask)) top = mid; else { if ((ucp_table[mid].f0 & f0_rangeflag) != 0 && - c <= (ucp_table[mid].f0 & f0_charmask) + - (ucp_table[mid].f1 & f1_rangemask)) break; + c <= (int)((ucp_table[mid].f0 & f0_charmask) + + (ucp_table[mid].f1 & f1_rangemask))) break; bot = mid + 1; } } diff --git a/libs/portaudio/src/hostapi/coreaudio/pa_mac_core_internal.h b/libs/portaudio/src/hostapi/coreaudio/pa_mac_core_internal.h index 291304c7e3..d2b5c105a1 100644 --- a/libs/portaudio/src/hostapi/coreaudio/pa_mac_core_internal.h +++ b/libs/portaudio/src/hostapi/coreaudio/pa_mac_core_internal.h @@ -63,6 +63,7 @@ #include #include +#include #include "portaudio.h" diff --git a/libs/silk/.update b/libs/silk/.update index c24155a58f..2863c1bd29 100644 --- a/libs/silk/.update +++ b/libs/silk/.update @@ -1 +1 @@ -Wed Mar 17 11:21:56 CDT 2010 +Tue Nov 1 11:51:42 CDT 2011 diff --git a/libs/silk/INSTALL b/libs/silk/INSTALL index 23e5f25d0e..7d1c323bea 100644 --- a/libs/silk/INSTALL +++ b/libs/silk/INSTALL @@ -1,16 +1,25 @@ Installation Instructions ************************* -Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free -Software Foundation, Inc. +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, +2006, 2007, 2008, 2009 Free Software Foundation, Inc. -This file is free documentation; the Free Software Foundation gives -unlimited permission to copy, distribute and modify it. + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. Basic Installation ================== -These are generic installation instructions. + Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. Some packages provide this +`INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses @@ -23,9 +32,9 @@ debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. (Caching is +the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale -cache files.) +cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail @@ -35,30 +44,37 @@ some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You only need -`configure.ac' if you want to change it or regenerate `configure' using -a newer version of `autoconf'. +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. -The simplest way to compile this package is: + The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. If you're - using `csh' on an old version of System V, you might need to type - `sh ./configure' instead to prevent `csh' from trying to execute - `configure' itself. + `./configure' to configure the package for your system. - Running `configure' takes awhile. While running, it prints some - messages telling which features it is checking for. + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with - the package. + the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and - documentation. + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the `make install' phase executed with root + privileges. - 5. You can remove the program binaries and object files from the + 5. Optionally, type `make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior `make install' required + root privileges, verifies that the installation completed + correctly. + + 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is @@ -67,45 +83,69 @@ The simplest way to compile this package is: all sorts of other programs in order to regenerate files that came with the distribution. + 7. Often, you can also type `make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide `make + distcheck', which can by used by developers to test that all other + targets like `make install' and `make uninstall' work correctly. + This target is generally not run by end users. + Compilers and Options ===================== -Some systems require unusual options for compilation or linking that the -`configure' script does not know about. Run `./configure --help' for -details on some of the pertinent environment variables. + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: - ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== -You can compile the package for more than one kind of computer at the + You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their -own directory. To do this, you must use a version of `make' that -supports the `VPATH' variable, such as GNU `make'. `cd' to the +own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. +source code in the directory that `configure' is in and in `..'. This +is known as a "VPATH" build. - If you have to use a `make' that does not support the `VPATH' -variable, you have to compile the package for one architecture at a -time in the source code directory. After you have installed the -package for one architecture, use `make distclean' before reconfiguring -for another architecture. + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple `-arch' options to the +compiler but only a single `-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the `lipo' tool if you have problems. Installation Names ================== -By default, `make install' installs the package's commands under + By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving -`configure' the option `--prefix=PREFIX'. +`configure' the option `--prefix=PREFIX', where PREFIX must be an +absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you @@ -116,16 +156,47 @@ Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. +you can set and what kinds of files go in them. In general, the +default for these options is expressed in terms of `${prefix}', so that +specifying just `--prefix' will affect all of the other directory +specifications that were not explicitly provided. + + The most portable way to affect installation locations is to pass the +correct locations to `configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +`make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, `make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +`${prefix}'. Any directories that were specified during `configure', +but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of +makefile variable overrides for each directory variable is required by +the GNU Coding Standards, and ideally causes no recompilation. +However, some platforms have known limitations with the semantics of +shared libraries that end up requiring recompilation when using this +method, particularly noticeable in packages that use GNU Libtool. + + The second method involves providing the `DESTDIR' variable. For +example, `make install DESTDIR=/alternate/directory' will prepend +`/alternate/directory' before all installation names. The approach of +`DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of `${prefix}' +at `configure' time. + +Optional Features +================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. -Optional Features -================= - -Some packages pay attention to `--enable-FEATURE' options to + Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The @@ -137,14 +208,53 @@ find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. + Some packages offer the ability to configure how verbose the +execution of `make' will be. For these packages, running `./configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with `make V=1'; while running `./configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with `make V=0'. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU +CC is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its `' header file. The option `-nodtk' can be used as +a workaround. If GNU CC is not installed, it is therefore recommended +to try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + + On Solaris, don't put `/usr/ucb' early in your `PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in `/usr/bin'. So, if you need `/usr/ucb' +in your `PATH', put it _after_ `/usr/bin'. + + On Haiku, software installed for all users goes in `/boot/common', +not `/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + Specifying the System Type ========================== -There may be some features `configure' cannot figure out automatically, -but needs to determine by the type of machine the package will run on. -Usually, assuming the package is built to be run on the _same_ -architectures, `configure' can figure that out, but if it prints a -message saying it cannot guess the machine type, give it the + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: @@ -152,7 +262,8 @@ type, such as `sun4', or a canonical name which has the form: where SYSTEM can have one of these forms: - OS KERNEL-OS + OS + KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't @@ -170,9 +281,9 @@ eventually be run) with `--host=TYPE'. Sharing Defaults ================ -If you want to set default values for `configure' scripts to share, you -can create a site shell script called `config.site' that gives default -values for variables like `CC', `cache_file', and `prefix'. + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. @@ -181,7 +292,7 @@ A warning: not all `configure' scripts look for a site script. Defining Variables ================== -Variables not defined in a site shell script can be set in the + Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set @@ -190,21 +301,29 @@ them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is -overridden in the site shell script). Here is a another example: +overridden in the site shell script). - /bin/bash ./configure CONFIG_SHELL=/bin/bash +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: -Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent -configuration-related scripts to be executed by `/bin/bash'. + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== -`configure' recognizes the following options to control how it operates. + `configure' recognizes the following options to control how it +operates. `--help' `-h' - Print a summary of the options to `configure', and exit. + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. `--version' `-V' @@ -231,6 +350,16 @@ configuration-related scripts to be executed by `/bin/bash'. Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. +`--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. diff --git a/libs/silk/Makefile.am b/libs/silk/Makefile.am index 071f1ecd64..ca98d4c97d 100644 --- a/libs/silk/Makefile.am +++ b/libs/silk/Makefile.am @@ -1,5 +1,5 @@ AM_CFLAGS = -Isrc -Iinterface -fPIC -O3 -AUTOMAKE_OPTS = gnu +AUTOMAKE_OPTIONS = gnu NAME = libSKP_SILK_SDK AM_CPPFLAGS = $(AM_CFLAGS) diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index 026754ace3..ac9e4fdecb 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Mon Aug 22 12:22:26 CDT 2011 +Fri Dec 16 10:29:41 CST 2011 diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c index 6064333ba3..923e8de416 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c @@ -827,10 +827,10 @@ static int nua_notify_usage_shutdown(nua_handle_t *nh, nua_dialog_usage_t *du) { struct notifier_usage *nu = nua_dialog_usage_private(du); - nua_client_request_t *cr = du->du_cr; + //nua_client_request_t *cr = du->du_cr; nu->nu_substate = nua_substate_terminated; - +#if 0 if (cr) { SU_DEBUG_5(("%s(%p, %p, %p): using existing cr=%p\n", "nua_notify_usage_shutdown", @@ -852,7 +852,7 @@ static int nua_notify_usage_shutdown(nua_handle_t *nh, TAG_END()) >= 0) return 0; } - +#endif nua_dialog_usage_remove(nh, ds, du, NULL, NULL); return 200; } diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_server.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_server.c index c8c42f44f9..50150a3a42 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_server.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_server.c @@ -158,14 +158,15 @@ int nua_stack_process_request(nua_handle_t *nh, /* These must be in-dialog */ sm = NULL; } - else if (initial && sip->sip_to->a_tag) { + else if (initial && sip->sip_to->a_tag && method != sip_method_subscribe) { /* RFC 3261 section 12.2.2: If the UAS wishes to reject the request because it does not wish to recreate the dialog, it MUST respond to the request with a 481 (Call/Transaction Does Not Exist) status code and pass that to the server transaction. - */ + */ /* we allow this on subscribes because we have disabled the built-in notify server and we need those messages in the application layer */ + if (method == sip_method_info) /* accept out-of-dialog info */; else if (method != sip_method_message || !NH_PGET(nh, win_messenger_enable)) diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c index bc80310f23..1958b5645a 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c @@ -4486,14 +4486,13 @@ session_timer_add_headers(struct session_timer *t, return 1; sip_add_tl(msg, sip, - TAG_IF(expires != 0, SIPTAG_SESSION_EXPIRES(x)), - TAG_IF(min != 0 - /* Min-SE: 0 is optional with initial INVITE */ - || !initial, - SIPTAG_MIN_SE(min_se)), - TAG_IF(refresher == nua_remote_refresher && expires != 0, - SIPTAG_REQUIRE_STR("timer")), - TAG_END()); + TAG_IF(expires != 0, SIPTAG_SESSION_EXPIRES(x)), + TAG_IF(min != 0 + /* Min-SE: 0 is optional with initial INVITE */ + || !initial, + SIPTAG_MIN_SE(min_se)), + //TAG_IF(refresher == nua_remote_refresher && expires != 0, SIPTAG_REQUIRE_STR("timer")), + TAG_END()); return 1; } diff --git a/libs/sofia-sip/libsofia-sip-ua/sdp/sdp_parse.c b/libs/sofia-sip/libsofia-sip-ua/sdp/sdp_parse.c index 6455f4b5c8..027544a00a 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sdp/sdp_parse.c +++ b/libs/sofia-sip/libsofia-sip-ua/sdp/sdp_parse.c @@ -1389,6 +1389,10 @@ void sdp_media_transport(sdp_media_t *m, char const *s) else if (su_casematch(s, "udptl")) /* Lower case - be compatible with people living by T.38 examples */ m->m_proto = sdp_proto_udptl, m->m_proto_name = "udptl"; + else if (su_casematch(s, "TCP/MSRP")) + m->m_proto = sdp_proto_msrp, m->m_proto_name = "TCP/MSRP"; + else if (su_casematch(s, "TCP/TLS/MSRP")) + m->m_proto = sdp_proto_msrps, m->m_proto_name = "TCP/TLS/MSRP"; else if (su_casematch(s, "UDP")) m->m_proto = sdp_proto_udp, m->m_proto_name = "UDP"; else if (su_casematch(s, "TCP")) diff --git a/libs/sofia-sip/libsofia-sip-ua/sdp/sdp_print.c b/libs/sofia-sip/libsofia-sip-ua/sdp/sdp_print.c index e94c6b6758..87c706b27c 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sdp/sdp_print.c +++ b/libs/sofia-sip/libsofia-sip-ua/sdp/sdp_print.c @@ -591,6 +591,8 @@ static void print_media(sdp_printer_t *p, case sdp_proto_rtp: proto = "RTP/AVP"; break; case sdp_proto_srtp: proto = "RTP/SAVP"; break; case sdp_proto_udptl: proto = "udptl"; break; + case sdp_proto_msrp: proto = "TCP/MSRP"; break; + case sdp_proto_msrps: proto = "TCP/TLS/MSRP"; break; case sdp_proto_tls: proto = "tls"; break; default: proto = m->m_proto_name; break; } diff --git a/libs/sofia-sip/libsofia-sip-ua/sdp/sofia-sip/sdp.h b/libs/sofia-sip/libsofia-sip-ua/sdp/sofia-sip/sdp.h index bb39bca54b..e4af3836a3 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sdp/sofia-sip/sdp.h +++ b/libs/sofia-sip/libsofia-sip-ua/sdp/sofia-sip/sdp.h @@ -243,6 +243,8 @@ typedef enum sdp_proto_rtp = 256, /**< RTP/AVP */ sdp_proto_srtp = 257, /**< RTP/SAVP */ sdp_proto_udptl = 258, /**< UDPTL. @NEW_1_12_4. */ + sdp_proto_msrp = 259, /**< TCP/MSRP @NEW_MSRP*/ + sdp_proto_msrps = 260, /**< TCP/TLS/MSRP @NEW_MSRP*/ sdp_proto_tls = 511, /**< TLS over TCP */ sdp_proto_any = 512 /**< * wildcard */ } sdp_proto_e; diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_logging.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_logging.c index fe23ce433a..e9d4f500b8 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_logging.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_logging.c @@ -385,7 +385,7 @@ void tport_capt_msg(tport_t const *self, msg_t *msg, size_t n, else hep_header.hp_p = IPPROTO_UDP; /* DEFAULT UDP */ /* Check destination */ - if(strncmp("recv", what, 4) == 0) dst = 1; + if(strncmp("sent", what, 4) == 0) dst = 1; /* copy destination and source IPs*/ if(su->su_family == AF_INET) { diff --git a/libs/spandsp/.update b/libs/spandsp/.update index bbfb583730..8822907a94 100644 --- a/libs/spandsp/.update +++ b/libs/spandsp/.update @@ -1 +1 @@ -Wed May 4 10:03:23 CDT 2011 +Tue Dec 6 17:55:59 CST 2011 diff --git a/libs/spandsp/config/ax_c99_features.m4 b/libs/spandsp/config/ax_c99_features.m4 index 6f9644884a..52ab00b543 100644 --- a/libs/spandsp/config/ax_c99_features.m4 +++ b/libs/spandsp/config/ax_c99_features.m4 @@ -47,8 +47,8 @@ AC_DEFUN([AX_C99_FUNC_LRINT], [AC_CACHE_CHECK(for lrint, ac_cv_c99_lrint, [ -lrint_save_CFLAGS=$CFLAGS -CFLAGS="-lm" +lrint_save_LIBS=$LIBS +LIBS="-lm" AC_TRY_LINK([ #define _ISOC9X_SOURCE 1 #define _ISOC99_SOURCE 1 @@ -58,7 +58,7 @@ AC_TRY_LINK([ #include ], if (!lrint(3.14159)) lrint(2.7183);, ac_cv_c99_lrint=yes, ac_cv_c99_lrint=no) -CFLAGS=$lrint_save_CFLAGS +LIBS=$lrint_save_LIBS ]) @@ -84,8 +84,8 @@ AC_DEFUN([AX_C99_FUNC_LRINTF], [AC_CACHE_CHECK(for lrintf, ac_cv_c99_lrintf, [ -lrintf_save_CFLAGS=$CFLAGS -CFLAGS="-lm" +lrintf_save_LIBS=$LIBS +LIBS="-lm" AC_TRY_LINK([ #define _ISOC9X_SOURCE 1 #define _ISOC99_SOURCE 1 @@ -95,7 +95,7 @@ AC_TRY_LINK([ #include ], if (!lrintf(3.14159)) lrintf(2.7183);, ac_cv_c99_lrintf=yes, ac_cv_c99_lrintf=no) -CFLAGS=$lrintf_save_CFLAGS +LIBS=$lrintf_save_LIBS ]) @@ -121,8 +121,8 @@ AC_DEFUN([AX_C99_FUNC_LLRINT], [AC_CACHE_CHECK(for llrint, ac_cv_c99_llrint, [ -llrint_save_CFLAGS=$CFLAGS -CFLAGS="-lm" +llrint_save_LIBS=$LIBS +LIBS="-lm" AC_TRY_LINK([ #define ISOC9X_SOURCE 1 #define _ISOC99_SOURCE 1 @@ -132,7 +132,7 @@ AC_TRY_LINK([ #include ], long long int x ; x = llrint(3.14159) ;, ac_cv_c99_llrint=yes, ac_cv_c99_llrint=no) -CFLAGS=$llrint_save_CFLAGS +LIBS=$llrint_save_LIBS ]) @@ -159,8 +159,8 @@ AC_DEFUN([AX_C99_FUNC_LLRINTF], [AC_CACHE_CHECK(for llrintf, ac_cv_c99_llrintf, [ -llrintf_save_CFLAGS=$CFLAGS -CFLAGS="-lm" +llrintf_save_LIBS=$LIBS +LIBS="-lm" AC_TRY_LINK([ #define _ISOC9X_SOURCE 1 #define _ISOC99_SOURCE 1 @@ -170,7 +170,7 @@ AC_TRY_LINK([ #include ], long long int x ; x = llrintf(3.14159) ;, ac_cv_c99_llrintf=yes, ac_cv_c99_llrintf=no) -CFLAGS=$llrintf_save_CFLAGS +LIBS=$llrintf_save_LIBS ]) diff --git a/libs/spandsp/config/ax_check_export_capability.m4 b/libs/spandsp/config/ax_check_export_capability.m4 index 37585393c2..952bb32139 100644 --- a/libs/spandsp/config/ax_check_export_capability.m4 +++ b/libs/spandsp/config/ax_check_export_capability.m4 @@ -28,8 +28,8 @@ gnu) )], [AC_MSG_RESULT([yes]) - COMP_VENDOR_CFLAGS="-fvisibility=hidden -DSWITCH_API_VISIBILITY=1 -DHAVE_VISIBILITY=1 $COMP_VENDOR_CFLAGS" - COMP_VENDOR_CXXFLAGS="-fvisibility=hidden -DSWITCH_API_VISIBILITY=1 -DHAVE_VISIBILITY=1 $COMP_VENDOR_CXXFLAGS" + COMP_VENDOR_CFLAGS="-fvisibility=hidden -DHAVE_VISIBILITY=1 $COMP_VENDOR_CFLAGS" + COMP_VENDOR_CXXFLAGS="-fvisibility=hidden -DHAVE_VISIBILITY=1 $COMP_VENDOR_CXXFLAGS" ac_cv_symbol_export_capability="yes"], [AC_MSG_RESULT([no])] @@ -47,8 +47,8 @@ sun) )], [AC_MSG_RESULT([yes]) - COMP_VENDOR_CFLAGS="-xldscope=hidden -DSWITCH_API_VISIBILITY=1 -DHAVE_VISIBILITY=1 $COMP_VENDOR_CFLAGS" - COMP_VENDOR_CXXFLAGS="-xldscope=hidden -DSWITCH_API_VISIBILITY=1 -DHAVE_VISIBILITY=1 $COMP_VENDOR_CXXFLAGS" + COMP_VENDOR_CFLAGS="-xldscope=hidden -DHAVE_VISIBILITY=1 $COMP_VENDOR_CFLAGS" + COMP_VENDOR_CXXFLAGS="-xldscope=hidden -DHAVE_VISIBILITY=1 $COMP_VENDOR_CXXFLAGS" ac_cv_symbol_export_capability="yes"], [AC_MSG_RESULT([no])] diff --git a/libs/spandsp/src/Makefile.am b/libs/spandsp/src/Makefile.am index 5c1f216586..96924bfe4c 100644 --- a/libs/spandsp/src/Makefile.am +++ b/libs/spandsp/src/Makefile.am @@ -319,16 +319,16 @@ nobase_include_HEADERS = spandsp/adsi.h \ nodist_include_HEADERS = spandsp.h -noinst_HEADERS = faxfont.h \ - filter_tools.h \ - gsm0610_local.h \ - lpc10_encdecs.h \ - mmx_sse_decs.h \ - t30_local.h \ - t4_t6_decode_states.h \ - v17_v32bis_rx_constellation_maps.h \ - v17_v32bis_tx_constellation_maps.h \ - v29tx_constellation_maps.h +noinst_HEADERS = faxfont.h \ + filter_tools.h \ + gsm0610_local.h \ + lpc10_encdecs.h \ + mmx_sse_decs.h \ + t30_local.h \ + t4_t6_decode_states.h \ + v17_v32bis_rx_constellation_maps.h \ + v17_v32bis_tx_constellation_maps.h \ + v29tx_constellation_maps.h make_at_dictionary$(EXEEXT): $(top_srcdir)/src/make_at_dictionary.c $(CC_FOR_BUILD) -o make_at_dictionary$(EXEEXT) $(top_srcdir)/src/make_at_dictionary.c -DHAVE_CONFIG_H -I$(top_builddir)/src diff --git a/libs/spandsp/src/bell_r2_mf.c b/libs/spandsp/src/bell_r2_mf.c index e61b782dc5..1487a821f5 100644 --- a/libs/spandsp/src/bell_r2_mf.c +++ b/libs/spandsp/src/bell_r2_mf.c @@ -43,6 +43,7 @@ #include "floating_fudge.h" #include "spandsp/telephony.h" +#include "spandsp/logging.h" #include "spandsp/fast_convert.h" #include "spandsp/queue.h" #include "spandsp/dc_restore.h" @@ -54,6 +55,7 @@ #include "spandsp/dtmf.h" #include "spandsp/bell_r2_mf.h" +#include "spandsp/private/logging.h" #include "spandsp/private/queue.h" #include "spandsp/private/tone_generate.h" #include "spandsp/private/bell_r2_mf.h" @@ -786,7 +788,7 @@ SPAN_DECLARE(int) r2_mf_rx(r2_mf_rx_state_t *s, const int16_t amp[], int samples } if (s->current_digit != hit_digit && s->callback) { - i = (hit_digit) ? -99 : -10; + i = (hit_digit) ? -10 : -99; s->callback(s->callback_data, hit_digit, i, 0); } s->current_digit = hit_digit; diff --git a/libs/spandsp/src/dds_int.c b/libs/spandsp/src/dds_int.c index 73eecb4077..df7a0a38cb 100644 --- a/libs/spandsp/src/dds_int.c +++ b/libs/spandsp/src/dds_int.c @@ -42,10 +42,6 @@ #include "spandsp/complex.h" #include "spandsp/dds.h" -#if !defined(M_PI) -# define M_PI 3.14159265358979323846 /* pi */ -#endif - /* In a A-law or u-law channel, a 128 step sine table is adequate to keep the spectral mess due to the DDS at a similar level to the spectral mess due to the A-law or u-law compression. */ diff --git a/libs/spandsp/src/dtmf.c b/libs/spandsp/src/dtmf.c index b07f8ec120..a0321c2030 100644 --- a/libs/spandsp/src/dtmf.c +++ b/libs/spandsp/src/dtmf.c @@ -29,8 +29,8 @@ #include "config.h" #endif -#include #include +#include #if defined(HAVE_TGMATH_H) #include #endif @@ -38,12 +38,12 @@ #include #endif #include "floating_fudge.h" +#include #include -#include -#include -#include +#include #include "spandsp/telephony.h" +#include "spandsp/logging.h" #include "spandsp/fast_convert.h" #include "spandsp/queue.h" #include "spandsp/complex.h" @@ -53,6 +53,7 @@ #include "spandsp/super_tone_rx.h" #include "spandsp/dtmf.h" +#include "spandsp/private/logging.h" #include "spandsp/private/queue.h" #include "spandsp/private/tone_generate.h" #include "spandsp/private/dtmf.h" @@ -165,6 +166,8 @@ SPAN_DECLARE(int) dtmf_rx(dtmf_rx_state_t *s, const int16_t amp[], int samples) goertzel_samplex(&s->row_out[3], xamp); goertzel_samplex(&s->col_out[3], xamp); } + if (s->duration < INT_MAX - (limit - sample)) + s->duration += (limit - sample); s->current_sample += (limit - sample); if (s->current_sample < DTMF_SAMPLES_PER_BLOCK) continue; @@ -188,29 +191,45 @@ SPAN_DECLARE(int) dtmf_rx(dtmf_rx_state_t *s, const int16_t amp[], int samples) /* Basic signal level test and the twist test */ if (row_energy[best_row] >= s->threshold && - col_energy[best_col] >= s->threshold - && - col_energy[best_col] < row_energy[best_row]*s->reverse_twist - && - col_energy[best_col]*s->normal_twist > row_energy[best_row]) + col_energy[best_col] >= s->threshold) { - /* Relative peak test ... */ - for (i = 0; i < 4; i++) + if (col_energy[best_col] < row_energy[best_row]*s->reverse_twist + && + col_energy[best_col]*s->normal_twist > row_energy[best_row]) { - if ((i != best_col && col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) - || - (i != best_row && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) + /* Relative peak test ... */ + for (i = 0; i < 4; i++) { - break; + if ((i != best_col && col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) + || + (i != best_row && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) + { + break; + } + } + /* ... and fraction of total energy test */ + if (i >= 4 + && + (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->energy) + { + /* Got a hit */ + hit = dtmf_positions[(best_row << 2) + best_col]; } } - /* ... and fraction of total energy test */ - if (i >= 4 - && - (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->energy) + if (span_log_test(&s->logging, SPAN_LOG_FLOW)) { - /* Got a hit */ - hit = dtmf_positions[(best_row << 2) + best_col]; + /* Log information about the quality of the signal, to aid analysis of detection problems */ + /* Logging at this point filters the total no-hoper frames out of the log, and leaves + anything which might feasibly be a DTMF digit. The log will then contain a list of the + total, row and coloumn power levels for detailed analysis of detection problems. */ + span_log(&s->logging, + SPAN_LOG_FLOW, + "Potentially '%c' - total %.2fdB, row %.2fdB, col %.2fdB - %s\n", + dtmf_positions[(best_row << 2) + best_col], + log10f(s->energy)*10.0f - DTMF_POWER_OFFSET + DBM0_MAX_POWER, + log10f(row_energy[best_row]/DTMF_TO_TOTAL_ENERGY)*10.0f - DTMF_POWER_OFFSET + DBM0_MAX_POWER, + log10f(col_energy[best_col]/DTMF_TO_TOTAL_ENERGY)*10.0f - DTMF_POWER_OFFSET + DBM0_MAX_POWER, + (hit) ? "hit" : "miss"); } } /* The logic in the next test should ensure the following for different successive hit patterns: @@ -251,7 +270,8 @@ SPAN_DECLARE(int) dtmf_rx(dtmf_rx_state_t *s, const int16_t amp[], int samples) if (s->in_digit || hit) { i = (s->in_digit && !hit) ? -99 : lfastrintf(log10f(s->energy)*10.0f - DTMF_POWER_OFFSET + DBM0_MAX_POWER); - s->realtime_callback(s->realtime_callback_data, hit, i, 0); + s->realtime_callback(s->realtime_callback_data, hit, i, s->duration); + s->duration = 0; } } else @@ -326,6 +346,7 @@ SPAN_DECLARE(void) dtmf_rx_set_realtime_callback(dtmf_rx_state_t *s, { s->realtime_callback = callback; s->realtime_callback_data = user_data; + s->duration = 0; } /*- End of function --------------------------------------------------------*/ @@ -357,6 +378,12 @@ SPAN_DECLARE(void) dtmf_rx_parms(dtmf_rx_state_t *s, } /*- End of function --------------------------------------------------------*/ +SPAN_DECLARE(logging_state_t *) dtmf_rx_get_logging_state(dtmf_rx_state_t *s) +{ + return &s->logging; +} +/*- End of function --------------------------------------------------------*/ + SPAN_DECLARE(dtmf_rx_state_t *) dtmf_rx_init(dtmf_rx_state_t *s, digits_rx_callback_t callback, void *user_data) @@ -369,6 +396,9 @@ SPAN_DECLARE(dtmf_rx_state_t *) dtmf_rx_init(dtmf_rx_state_t *s, if ((s = (dtmf_rx_state_t *) malloc(sizeof (*s))) == NULL) return NULL; } + memset(s, 0, sizeof(*s)); + span_log_init(&s->logging, SPAN_LOG_NONE, NULL); + span_log_set_protocol(&s->logging, "DTMF"); s->digits_callback = callback; s->digits_callback_data = user_data; s->realtime_callback = NULL; @@ -519,6 +549,7 @@ SPAN_DECLARE(dtmf_tx_state_t *) dtmf_tx_init(dtmf_tx_state_t *s) if ((s = (dtmf_tx_state_t *) malloc(sizeof (*s))) == NULL) return NULL; } + memset(s, 0, sizeof(*s)); if (!dtmf_tx_inited) dtmf_tx_initialise(); tone_gen_init(&(s->tones), &dtmf_digit_tones[0]); diff --git a/libs/spandsp/src/fax.c b/libs/spandsp/src/fax.c index ae10069e82..422315f2d0 100644 --- a/libs/spandsp/src/fax.c +++ b/libs/spandsp/src/fax.c @@ -71,12 +71,21 @@ #include "spandsp/v27ter_rx.h" #include "spandsp/v17tx.h" #include "spandsp/v17rx.h" +#include "spandsp/timezone.h" #include "spandsp/t4_rx.h" #include "spandsp/t4_tx.h" -#if defined(SPANDSP_SUPPORT_T85) +#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) || defined(SPANDSP_SUPPORT_T85) #include "spandsp/t81_t82_arith_coding.h" +#endif +#if defined(SPANDSP_SUPPORT_T85) #include "spandsp/t85.h" #endif +#if defined(SPANDSP_SUPPORT_T42) +#include "spandsp/t42.h" +#endif +#if defined(SPANDSP_SUPPORT_T43) +#include "spandsp/t43.h" +#endif #include "spandsp/t4_t6_decode.h" #include "spandsp/t4_t6_encode.h" @@ -102,10 +111,19 @@ #include "spandsp/private/v29rx.h" #include "spandsp/private/hdlc.h" #include "spandsp/private/fax_modems.h" -#if defined(SPANDSP_SUPPORT_T85) +#include "spandsp/private/timezone.h" +#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) || defined(SPANDSP_SUPPORT_T85) #include "spandsp/private/t81_t82_arith_coding.h" +#endif +#if defined(SPANDSP_SUPPORT_T85) #include "spandsp/private/t85.h" #endif +#if defined(SPANDSP_SUPPORT_T42) +#include "spandsp/private/t42.h" +#endif +#if defined(SPANDSP_SUPPORT_T43) +#include "spandsp/private/t43.h" +#endif #include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/t4_rx.h" diff --git a/libs/spandsp/src/image_translate.c b/libs/spandsp/src/image_translate.c index 3a3b86ff9d..beba3dab07 100644 --- a/libs/spandsp/src/image_translate.c +++ b/libs/spandsp/src/image_translate.c @@ -54,21 +54,38 @@ #include "spandsp/fast_convert.h" #include "spandsp/logging.h" #include "spandsp/saturated.h" +#include "spandsp/timezone.h" #include "spandsp/t4_rx.h" #include "spandsp/t4_tx.h" -#if defined(SPANDSP_SUPPORT_T85) +#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) || defined(SPANDSP_SUPPORT_T85) #include "spandsp/t81_t82_arith_coding.h" +#endif +#if defined(SPANDSP_SUPPORT_T85) #include "spandsp/t85.h" #endif +#if defined(SPANDSP_SUPPORT_T42) +#include "spandsp/t42.h" +#endif +#if defined(SPANDSP_SUPPORT_T43) +#include "spandsp/t43.h" +#endif #include "spandsp/t4_t6_decode.h" #include "spandsp/t4_t6_encode.h" #include "spandsp/image_translate.h" #include "spandsp/private/logging.h" -#if defined(SPANDSP_SUPPORT_T85) +#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) || defined(SPANDSP_SUPPORT_T85) #include "spandsp/private/t81_t82_arith_coding.h" +#endif +#if defined(SPANDSP_SUPPORT_T85) #include "spandsp/private/t85.h" #endif +#if defined(SPANDSP_SUPPORT_T42) +#include "spandsp/private/t42.h" +#endif +#if defined(SPANDSP_SUPPORT_T43) +#include "spandsp/private/t43.h" +#endif #include "spandsp/private/t4_t6_decode.h" #include "spandsp/private/t4_t6_encode.h" #include "spandsp/private/t4_rx.h" diff --git a/libs/spandsp/src/msvc/spandsp.h b/libs/spandsp/src/msvc/spandsp.h index deb146884e..95ee8bf11b 100644 --- a/libs/spandsp/src/msvc/spandsp.h +++ b/libs/spandsp/src/msvc/spandsp.h @@ -99,6 +99,7 @@ #include #include #include +#include #include #include #include diff --git a/libs/spandsp/src/plc.c b/libs/spandsp/src/plc.c index 3d07417f68..392a7b01a6 100644 --- a/libs/spandsp/src/plc.c +++ b/libs/spandsp/src/plc.c @@ -165,8 +165,10 @@ SPAN_DECLARE(int) plc_fillin(plc_state_t *s, int16_t amp[], int len) float old_weight; float new_weight; float gain; + //int16_t *orig_amp; int orig_len; + //orig_amp = amp; orig_len = len; if (s->missing_samples == 0) { diff --git a/libs/spandsp/src/spandsp.h.in b/libs/spandsp/src/spandsp.h.in index eaed548c97..acb8a18ed5 100644 --- a/libs/spandsp/src/spandsp.h.in +++ b/libs/spandsp/src/spandsp.h.in @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -97,6 +98,7 @@ #include /*#include */ #include +#include #include #include #include @@ -126,7 +128,6 @@ #include #include #include -#include #endif diff --git a/libs/spandsp/src/spandsp/dtmf.h b/libs/spandsp/src/spandsp/dtmf.h index 60b2f65183..bca36cf015 100644 --- a/libs/spandsp/src/spandsp/dtmf.h +++ b/libs/spandsp/src/spandsp/dtmf.h @@ -186,6 +186,11 @@ SPAN_DECLARE(int) dtmf_rx_status(dtmf_rx_state_t *s); \return The number of digits actually returned. */ SPAN_DECLARE(size_t) dtmf_rx_get(dtmf_rx_state_t *s, char *digits, int max); +/*! \brief Get the logging context associated with a DTMF receiver context. + \param s The DTMF receiver context. + \return A pointer to the logging context */ +SPAN_DECLARE(logging_state_t *) dtmf_rx_get_logging_state(dtmf_rx_state_t *s); + /*! \brief Initialise a DTMF receiver context. \param s The DTMF receiver context. \param callback An optional callback routine, used to report received digits. If diff --git a/libs/spandsp/src/spandsp/expose.h b/libs/spandsp/src/spandsp/expose.h index ca2274d9f7..6989a3faae 100644 --- a/libs/spandsp/src/spandsp/expose.h +++ b/libs/spandsp/src/spandsp/expose.h @@ -72,6 +72,7 @@ /*#include */ #include #include +#include #include #include #include @@ -88,7 +89,6 @@ #include #include #include -#include #include #include #include diff --git a/libs/spandsp/src/spandsp/private/dtmf.h b/libs/spandsp/src/spandsp/private/dtmf.h index eeacff16d3..dc9c17bffc 100644 --- a/libs/spandsp/src/spandsp/private/dtmf.h +++ b/libs/spandsp/src/spandsp/private/dtmf.h @@ -96,6 +96,9 @@ struct dtmf_rx_state_s uint8_t in_digit; /*! The current sample number within a processing block. */ int current_sample; + + /*! Tone state duration */ + int duration; /*! The number of digits which have been lost due to buffer overflows. */ int lost_digits; @@ -103,6 +106,9 @@ struct dtmf_rx_state_s int current_digits; /*! The received digits buffer. This is a NULL terminated string. */ char digits[MAX_DTMF_DIGITS + 1]; + + /*! \brief Error and flow logging control */ + logging_state_t logging; }; #endif diff --git a/libs/spandsp/src/spandsp/private/fax.h b/libs/spandsp/src/spandsp/private/fax.h index c75f4fa01e..9e99a10751 100644 --- a/libs/spandsp/src/spandsp/private/fax.h +++ b/libs/spandsp/src/spandsp/private/fax.h @@ -40,7 +40,7 @@ struct fax_state_s /*! \brief The analogue modem front-end */ fax_modems_state_t modems; /*! \brief V.8 */ - //v8_state_t v8; + v8_state_t v8; /*! \brief Error and flow logging control */ logging_state_t logging; diff --git a/libs/spandsp/src/spandsp/private/t30.h b/libs/spandsp/src/spandsp/private/t30.h index b8a2e8be1c..8cd890b9e0 100644 --- a/libs/spandsp/src/spandsp/private/t30.h +++ b/libs/spandsp/src/spandsp/private/t30.h @@ -73,6 +73,11 @@ struct t30_state_s page image. FALSE for FAX page headers to add to the overall length of the page. */ int header_overlays_image; + /*! \brief Use private timezone if TRUE */ + int use_own_tz; + /*! \brief Optional per instance time zone for the FAX page header timestamp. */ + tz_t tz; + /*! \brief TRUE if remote T.30 procedural interrupts are allowed. */ int remote_interrupts_allowed; diff --git a/libs/spandsp/src/spandsp/private/t31.h b/libs/spandsp/src/spandsp/private/t31.h index a2d8f97199..ee481c5151 100644 --- a/libs/spandsp/src/spandsp/private/t31.h +++ b/libs/spandsp/src/spandsp/private/t31.h @@ -33,7 +33,7 @@ typedef struct { fax_modems_state_t modems; - //v8_state_t v8; + v8_state_t v8; /*! The transmit signal handler to be used when the current one has finished sending. */ span_tx_handler_t *next_tx_handler; diff --git a/libs/spandsp/src/spandsp/private/t38_terminal.h b/libs/spandsp/src/spandsp/private/t38_terminal.h index 6681f9321c..a78ec685f7 100644 --- a/libs/spandsp/src/spandsp/private/t38_terminal.h +++ b/libs/spandsp/src/spandsp/private/t38_terminal.h @@ -96,7 +96,7 @@ typedef struct /*! \brief The value for samples at the next transmission point. */ int32_t next_tx_samples; /*! \brief The current transmit timeout. */ - //int32_t timeout_tx_samples; + int32_t timeout_tx_samples; /*! \brief The current receive timeout. */ int32_t timeout_rx_samples; } t38_terminal_front_end_state_t; diff --git a/libs/spandsp/src/spandsp/private/t4_tx.h b/libs/spandsp/src/spandsp/private/t4_tx.h index a30f7ba7aa..9153b47e8b 100644 --- a/libs/spandsp/src/spandsp/private/t4_tx.h +++ b/libs/spandsp/src/spandsp/private/t4_tx.h @@ -49,8 +49,8 @@ struct t4_state_s /*! \brief The text which will be used in FAX page header. No text results in no header line. */ const char *header_info; - /*! \brief Optional per instance time zone for the FAX pager header timestamp. */ - struct tz_s *tz; + /*! \brief Optional per instance time zone for the FAX page header timestamp. */ + tz_t *tz; /*! \brief The size of the compressed image on the line side, in bits. */ int line_image_size; diff --git a/libs/spandsp/src/spandsp/private/v17rx.h b/libs/spandsp/src/spandsp/private/v17rx.h index 9bf9149dbc..8da0967a4a 100644 --- a/libs/spandsp/src/spandsp/private/v17rx.h +++ b/libs/spandsp/src/spandsp/private/v17rx.h @@ -72,77 +72,6 @@ struct v17_rx_state_s routine. */ void *qam_user_data; - /*! \brief The route raised cosine (RRC) pulse shaping filter buffer. */ -#if defined(SPANDSP_USE_FIXED_POINT) - int16_t rrc_filter[V17_RX_FILTER_STEPS]; -#else - float rrc_filter[V17_RX_FILTER_STEPS]; -#endif - /*! \brief Current offset into the RRC pulse shaping filter buffer. */ - int rrc_filter_step; - - /*! \brief The state of the differential decoder */ - int diff; - /*! \brief The register for the data scrambler. */ - uint32_t scramble_reg; - /*! \brief Scrambler tap */ - int scrambler_tap; - - /*! \brief TRUE if the short training sequence is to be used. */ - int short_train; - /*! \brief The section of the training data we are currently in. */ - int training_stage; - /*! \brief A count of how far through the current training step we are. */ - int training_count; - /*! \brief A measure of how much mismatch there is between the real constellation, - and the decoded symbol positions. */ - float training_error; - /*! \brief The value of the last signal sample, using the a simple HPF for signal power estimation. */ - int16_t last_sample; - /*! \brief >0 if a signal above the minimum is present. It may or may not be a V.17 signal. */ - int signal_present; - /*! \brief Whether or not a carrier drop was detected and the signal delivery is pending. */ - int carrier_drop_pending; - /*! \brief A count of the current consecutive samples below the carrier off threshold. */ - int low_samples; - /*! \brief A highest magnitude sample seen. */ - int16_t high_sample; - - /*! \brief The current phase of the carrier (i.e. the DDS parameter). */ - uint32_t carrier_phase; - /*! \brief The update rate for the phase of the carrier (i.e. the DDS increment). */ - int32_t carrier_phase_rate; - /*! \brief The carrier update rate saved for reuse when using short training. */ - int32_t carrier_phase_rate_save; -#if defined(SPANDSP_USE_FIXED_POINTx) - /*! \brief The proportional part of the carrier tracking filter. */ - float carrier_track_p; - /*! \brief The integral part of the carrier tracking filter. */ - float carrier_track_i; -#else - /*! \brief The proportional part of the carrier tracking filter. */ - float carrier_track_p; - /*! \brief The integral part of the carrier tracking filter. */ - float carrier_track_i; -#endif - - /*! \brief A power meter, to measure the HPF'ed signal power in the channel. */ - power_meter_t power; - /*! \brief The power meter level at which carrier on is declared. */ - int32_t carrier_on_power; - /*! \brief The power meter level at which carrier off is declared. */ - int32_t carrier_off_power; - - /*! \brief Current read offset into the equalizer buffer. */ - int eq_step; - /*! \brief Current write offset into the equalizer buffer. */ - int eq_put_step; - /*! \brief Symbol count to the next equalizer update. */ - int eq_skip; - - /*! \brief The current half of the baud. */ - int baud_half; - #if defined(SPANDSP_USE_FIXED_POINTx) /*! \brief The scaling factor accessed by the AGC algorithm. */ float agc_scaling; @@ -166,6 +95,20 @@ struct v17_rx_state_s int32_t symbol_sync_dc_filter[2]; /*! Baud phase for symbol sync. */ int32_t baud_phase; + + /*! \brief A measure of how much mismatch there is between the real constellation, + and the decoded symbol positions. */ + float training_error; + + /*! \brief The proportional part of the carrier tracking filter. */ + float carrier_track_p; + /*! \brief The integral part of the carrier tracking filter. */ + float carrier_track_i; + /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */ + int16_t rrc_filter[V17_RX_FILTER_STEPS]; + + /*! \brief A pointer to the current constellation. */ + const complexi16_t *constellation; #else /*! \brief The scaling factor accessed by the AGC algorithm. */ float agc_scaling; @@ -189,7 +132,71 @@ struct v17_rx_state_s float symbol_sync_dc_filter[2]; /*! Baud phase for symbol sync. */ float baud_phase; + + /*! \brief A measure of how much mismatch there is between the real constellation, + and the decoded symbol positions. */ + float training_error; + + /*! \brief The proportional part of the carrier tracking filter. */ + float carrier_track_p; + /*! \brief The integral part of the carrier tracking filter. */ + float carrier_track_i; + /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */ + float rrc_filter[V17_RX_FILTER_STEPS]; + + /*! \brief A pointer to the current constellation. */ + const complexf_t *constellation; #endif + /*! \brief Current offset into the RRC pulse shaping filter buffer. */ + int rrc_filter_step; + + /*! \brief The state of the differential decoder */ + int diff; + /*! \brief The register for the data scrambler. */ + uint32_t scramble_reg; + /*! \brief Scrambler tap */ + int scrambler_tap; + + /*! \brief TRUE if the short training sequence is to be used. */ + int short_train; + /*! \brief The section of the training data we are currently in. */ + int training_stage; + /*! \brief A count of how far through the current training step we are. */ + int training_count; + /*! \brief The value of the last signal sample, using the a simple HPF for signal power estimation. */ + int16_t last_sample; + /*! \brief >0 if a signal above the minimum is present. It may or may not be a V.17 signal. */ + int signal_present; + /*! \brief Whether or not a carrier drop was detected and the signal delivery is pending. */ + int carrier_drop_pending; + /*! \brief A count of the current consecutive samples below the carrier off threshold. */ + int low_samples; + /*! \brief A highest magnitude sample seen. */ + int16_t high_sample; + + /*! \brief The current phase of the carrier (i.e. the DDS parameter). */ + uint32_t carrier_phase; + /*! \brief The update rate for the phase of the carrier (i.e. the DDS increment). */ + int32_t carrier_phase_rate; + /*! \brief The carrier update rate saved for reuse when using short training. */ + int32_t carrier_phase_rate_save; + + /*! \brief A power meter, to measure the HPF'ed signal power in the channel. */ + power_meter_t power; + /*! \brief The power meter level at which carrier on is declared. */ + int32_t carrier_on_power; + /*! \brief The power meter level at which carrier off is declared. */ + int32_t carrier_off_power; + + /*! \brief Current read offset into the equalizer buffer. */ + int eq_step; + /*! \brief Current write offset into the equalizer buffer. */ + int eq_put_step; + /*! \brief Symbol count to the next equalizer update. */ + int eq_skip; + + /*! \brief The current half of the baud. */ + int baud_half; /*! \brief The total symbol timing correction since the carrier came up. This is only for performance analysis purposes. */ @@ -199,12 +206,7 @@ struct v17_rx_state_s int32_t start_angles[2]; /*! \brief History list of phase angles for the coarse carrier aquisition step. */ int32_t angles[16]; - /*! \brief A pointer to the current constellation. */ -#if defined(SPANDSP_USE_FIXED_POINTx) - const complexi16_t *constellation; -#else - const complexf_t *constellation; -#endif + /*! \brief A pointer to the current space map. There is a space map for each trellis state. */ int space_map; @@ -217,13 +219,16 @@ struct v17_rx_state_s int full_path_to_past_state_locations[V17_TRELLIS_STORAGE_DEPTH][8]; /*! \brief The trellis. */ int past_state_locations[V17_TRELLIS_STORAGE_DEPTH][8]; +#if defined(SPANDSP_USE_FIXED_POINTx) /*! \brief Euclidean distances (actually the squares of the distances) from the last states of the trellis. */ -#if defined(SPANDSP_USE_FIXED_POINTx) uint32_t distances[8]; #else + /*! \brief Euclidean distances (actually the squares of the distances) + from the last states of the trellis. */ float distances[8]; #endif + /*! \brief Error and flow logging control */ logging_state_t logging; }; diff --git a/libs/spandsp/src/spandsp/private/v17tx.h b/libs/spandsp/src/spandsp/private/v17tx.h index badbd799b0..f6c9d21343 100644 --- a/libs/spandsp/src/spandsp/private/v17tx.h +++ b/libs/spandsp/src/spandsp/private/v17tx.h @@ -49,23 +49,24 @@ struct v17_tx_state_s /*! \brief A user specified opaque pointer passed to the status function. */ void *status_user_data; +#if defined(SPANDSP_USE_FIXED_POINT) /*! \brief The gain factor needed to achieve the specified output power. */ -#if defined(SPANDSP_USE_FIXED_POINT) - int32_t gain; -#else - float gain; -#endif - - /*! \brief The route raised cosine (RRC) pulse shaping filter buffer. */ -#if defined(SPANDSP_USE_FIXED_POINT) + int16_t gain; + /*! \brief A pointer to the constellation currently in use. */ + const complexi16_t *constellation; /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */ int16_t rrc_filter_re[V17_TX_FILTER_STEPS]; int16_t rrc_filter_im[V17_TX_FILTER_STEPS]; #else + /*! \brief The gain factor needed to achieve the specified output power. */ + float gain; + /*! \brief A pointer to the constellation currently in use. */ + const complexf_t *constellation; /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */ float rrc_filter_re[V17_TX_FILTER_STEPS]; float rrc_filter_im[V17_TX_FILTER_STEPS]; #endif + /*! \brief Current offset into the RRC pulse shaping filter buffer. */ int rrc_filter_step; @@ -94,12 +95,6 @@ struct v17_tx_state_s /*! \brief The current fractional phase of the baud timing. */ int baud_phase; - /*! \brief A pointer to the constellation currently in use. */ -#if defined(SPANDSP_USE_FIXED_POINT) - const complexi16_t *constellation; -#else - const complexf_t *constellation; -#endif /*! \brief The current number of data bits per symbol. This does not include the redundant bit. */ int bits_per_symbol; diff --git a/libs/spandsp/src/spandsp/private/v22bis.h b/libs/spandsp/src/spandsp/private/v22bis.h index d81bd039c5..2561c8e03d 100644 --- a/libs/spandsp/src/spandsp/private/v22bis.h +++ b/libs/spandsp/src/spandsp/private/v22bis.h @@ -26,16 +26,16 @@ #if !defined(_SPANDSP_PRIVATE_V22BIS_H_) #define _SPANDSP_PRIVATE_V22BIS_H_ -/*! The number of steps to the left and to the right of the target position in the equalizer buffer. */ -#define V22BIS_EQUALIZER_LEN 7 -/*! One less than a power of 2 >= (2*V22BIS_EQUALIZER_LEN + 1) */ -#define V22BIS_EQUALIZER_MASK 15 +/*! The length of the equalizer buffer */ +#define V22BIS_EQUALIZER_LEN 17 +/*! Samples before the target position in the equalizer buffer */ +#define V22BIS_EQUALIZER_PRE_LEN 8 /*! The number of taps in the transmit pulse shaping filter */ -#define V22BIS_TX_FILTER_STEPS 9 +#define V22BIS_TX_FILTER_STEPS 9 /*! The number of taps in the receive pulse shaping/bandpass filter */ -#define V22BIS_RX_FILTER_STEPS 27 +#define V22BIS_RX_FILTER_STEPS 27 /*! Segments of the training sequence on the receive side */ enum @@ -65,6 +65,12 @@ enum V22BIS_TX_TRAINING_STAGE_PARKED }; +#if defined(SPANDSP_USE_FIXED_POINT) +extern const complexi16_t v22bis_constellation[16]; +#else +extern const complexf_t v22bis_constellation[16]; +#endif + /*! V.22bis modem descriptor. This defines the working state for a single instance of a V.22bis modem. @@ -93,10 +99,15 @@ struct v22bis_state_s /* Receive section */ struct { - /*! \brief The route raised cosine (RRC) pulse shaping filter buffer. */ -#if defined(SPANDSP_USE_FIXED_POINTx) +#if defined(SPANDSP_USE_FIXED_POINT) + /*! \brief The scaling factor accessed by the AGC algorithm. */ + int16_t agc_scaling; + /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */ int16_t rrc_filter[V22BIS_RX_FILTER_STEPS]; #else + /*! \brief The scaling factor accessed by the AGC algorithm. */ + float agc_scaling; + /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */ float rrc_filter[V22BIS_RX_FILTER_STEPS]; #endif /*! \brief Current offset into the RRC pulse shaping filter buffer. */ @@ -116,19 +127,28 @@ struct v22bis_state_s /*! \brief >0 if a signal above the minimum is present. It may or may not be a V.22bis signal. */ int signal_present; - /*! \brief A measure of how much mismatch there is between the real constellation, - and the decoded symbol positions. */ - float training_error; - /*! \brief The current phase of the carrier (i.e. the DDS parameter). */ uint32_t carrier_phase; /*! \brief The update rate for the phase of the carrier (i.e. the DDS increment). */ int32_t carrier_phase_rate; +#if defined(SPANDSP_USE_FIXED_POINT) + /*! \brief A measure of how much mismatch there is between the real constellation, + and the decoded symbol positions. */ + int32_t training_error; + /*! \brief The proportional part of the carrier tracking filter. */ + int32_t carrier_track_p; + /*! \brief The integral part of the carrier tracking filter. */ + int32_t carrier_track_i; +#else + /*! \brief A measure of how much mismatch there is between the real constellation, + and the decoded symbol positions. */ + float training_error; /*! \brief The proportional part of the carrier tracking filter. */ float carrier_track_p; /*! \brief The integral part of the carrier tracking filter. */ float carrier_track_i; - +#endif + /*! \brief A callback function which may be enabled to report every symbol's constellation position. */ qam_report_handler_t qam_report; @@ -142,21 +162,23 @@ struct v22bis_state_s int32_t carrier_on_power; /*! \brief The power meter level at which carrier off is declared. */ int32_t carrier_off_power; - /*! \brief The scaling factor accessed by the AGC algorithm. */ - float agc_scaling; - + int constellation_state; +#if defined(SPANDSP_USE_FIXED_POINT) + /*! \brief The current delta factor for updating the equalizer coefficients. */ + int16_t eq_delta; + /*! \brief The adaptive equalizer coefficients. */ + complexi16_t eq_coeff[V22BIS_EQUALIZER_LEN]; + /*! \brief The equalizer signal buffer. */ + complexi16_t eq_buf[V22BIS_EQUALIZER_LEN]; +#else /*! \brief The current delta factor for updating the equalizer coefficients. */ float eq_delta; -#if defined(SPANDSP_USE_FIXED_POINTx) /*! \brief The adaptive equalizer coefficients. */ - complexi_t eq_coeff[2*V22BIS_EQUALIZER_LEN + 1]; + complexf_t eq_coeff[V22BIS_EQUALIZER_LEN]; /*! \brief The equalizer signal buffer. */ - complexi_t eq_buf[V22BIS_EQUALIZER_MASK + 1]; -#else - complexf_t eq_coeff[2*V22BIS_EQUALIZER_LEN + 1]; - complexf_t eq_buf[V22BIS_EQUALIZER_MASK + 1]; + complexf_t eq_buf[V22BIS_EQUALIZER_LEN]; #endif /*! \brief Current offset into the equalizer buffer. */ int eq_step; @@ -182,16 +204,29 @@ struct v22bis_state_s /* Transmit section */ struct { +#if defined(SPANDSP_USE_FIXED_POINT) + /*! \brief The guard tone level. */ + int16_t guard_tone_gain; + /*! \brief The gain factor needed to achieve the specified output power. */ + int16_t gain; + /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */ + int16_t rrc_filter_re[V22BIS_TX_FILTER_STEPS]; + int16_t rrc_filter_im[V22BIS_TX_FILTER_STEPS]; +#else + /*! \brief The guard tone level. */ + float guard_tone_gain; /*! \brief The gain factor needed to achieve the specified output power. */ float gain; + /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */ + float rrc_filter_re[V22BIS_TX_FILTER_STEPS]; + float rrc_filter_im[V22BIS_TX_FILTER_STEPS]; +#endif - /*! \brief The route raised cosine (RRC) pulse shaping filter buffer. */ - complexf_t rrc_filter[2*V22BIS_TX_FILTER_STEPS]; /*! \brief Current offset into the RRC pulse shaping filter buffer. */ int rrc_filter_step; /*! \brief The register for the data scrambler. */ - unsigned int scramble_reg; + uint32_t scramble_reg; /*! \brief A counter for the number of consecutive bits of repeating pattern through the scrambler. */ int scrambler_pattern_count; @@ -208,7 +243,6 @@ struct v22bis_state_s uint32_t guard_phase; /*! \brief The update rate for the phase of the guard tone (i.e. the DDS increment). */ int32_t guard_phase_rate; - float guard_level; /*! \brief The current fractional phase of the baud timing. */ int baud_phase; /*! \brief The code number for the current position in the constellation. */ diff --git a/libs/spandsp/src/spandsp/private/v27ter_rx.h b/libs/spandsp/src/spandsp/private/v27ter_rx.h index 8ae99b4f81..4a991ba3f5 100644 --- a/libs/spandsp/src/spandsp/private/v27ter_rx.h +++ b/libs/spandsp/src/spandsp/private/v27ter_rx.h @@ -69,17 +69,62 @@ struct v27ter_rx_state_s routine. */ void *qam_user_data; - /*! \brief The route raised cosine (RRC) pulse shaping filter buffer. */ #if defined(SPANDSP_USE_FIXED_POINT) + /*! \brief The scaling factor accessed by the AGC algorithm. */ + int16_t agc_scaling; + /*! \brief The previous value of agc_scaling, needed to reuse old training. */ + int16_t agc_scaling_save; + + /*! \brief The current delta factor for updating the equalizer coefficients. */ + float eq_delta; + /*! \brief The adaptive equalizer coefficients. */ + /*complexi16_t*/ complexf_t eq_coeff[V27TER_EQUALIZER_LEN]; + /*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */ + /*complexi16_t*/ complexf_t eq_coeff_save[V27TER_EQUALIZER_LEN]; + /*! \brief The equalizer signal buffer. */ + /*complexi16_t*/ complexf_t eq_buf[V27TER_EQUALIZER_LEN]; + + /*! \brief A measure of how much mismatch there is between the real constellation, + and the decoded symbol positions. */ + float training_error; + + /*! \brief The proportional part of the carrier tracking filter. */ + float carrier_track_p; + /*! \brief The integral part of the carrier tracking filter. */ + float carrier_track_i; + /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */ int16_t rrc_filter[V27TER_RX_FILTER_STEPS]; #else + /*! \brief The scaling factor accessed by the AGC algorithm. */ + float agc_scaling; + /*! \brief The previous value of agc_scaling, needed to reuse old training. */ + float agc_scaling_save; + + /*! \brief The current delta factor for updating the equalizer coefficients. */ + float eq_delta; + /*! \brief The adaptive equalizer coefficients. */ + complexf_t eq_coeff[V27TER_EQUALIZER_LEN]; + /*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */ + complexf_t eq_coeff_save[V27TER_EQUALIZER_LEN]; + /*! \brief The equalizer signal buffer. */ + complexf_t eq_buf[V27TER_EQUALIZER_LEN]; + + /*! \brief A measure of how much mismatch there is between the real constellation, + and the decoded symbol positions. */ + float training_error; + + /*! \brief The proportional part of the carrier tracking filter. */ + float carrier_track_p; + /*! \brief The integral part of the carrier tracking filter. */ + float carrier_track_i; + /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */ float rrc_filter[V27TER_RX_FILTER_STEPS]; #endif /*! \brief Current offset into the RRC pulse shaping filter buffer. */ int rrc_filter_step; /*! \brief The register for the training and data scrambler. */ - unsigned int scramble_reg; + uint32_t scramble_reg; /*! \brief A counter for the number of consecutive bits of repeating pattern through the scrambler. */ int scrambler_pattern_count; @@ -91,9 +136,6 @@ struct v27ter_rx_state_s int training_stage; /*! \brief A count of how far through the current training step we are. */ int training_count; - /*! \brief A measure of how much mismatch there is between the real constellation, - and the decoded symbol positions. */ - float training_error; /*! \brief The value of the last signal sample, using the a simple HPF for signal power estimation. */ int16_t last_sample; /*! \brief >0 if a signal above the minimum is present. It may or may not be a V.27ter signal. */ @@ -115,17 +157,6 @@ struct v27ter_rx_state_s int32_t carrier_phase_rate; /*! \brief The carrier update rate saved for reuse when using short training. */ int32_t carrier_phase_rate_save; -#if defined(SPANDSP_USE_FIXED_POINTx) - /*! \brief The proportional part of the carrier tracking filter. */ - float carrier_track_p; - /*! \brief The integral part of the carrier tracking filter. */ - float carrier_track_i; -#else - /*! \brief The proportional part of the carrier tracking filter. */ - float carrier_track_p; - /*! \brief The integral part of the carrier tracking filter. */ - float carrier_track_i; -#endif /*! \brief A power meter, to measure the HPF'ed signal power in the channel. */ power_meter_t power; @@ -144,36 +175,6 @@ struct v27ter_rx_state_s /*! \brief The current half of the baud. */ int baud_half; -#if defined(SPANDSP_USE_FIXED_POINT) - /*! \brief The scaling factor accessed by the AGC algorithm. */ - int16_t agc_scaling; - /*! \brief The previous value of agc_scaling, needed to reuse old training. */ - int16_t agc_scaling_save; - - /*! \brief The current delta factor for updating the equalizer coefficients. */ - float eq_delta; - /*! \brief The adaptive equalizer coefficients. */ - /*complexi16_t*/ complexf_t eq_coeff[V27TER_EQUALIZER_LEN]; - /*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */ - /*complexi16_t*/ complexf_t eq_coeff_save[V27TER_EQUALIZER_LEN]; - /*! \brief The equalizer signal buffer. */ - /*complexi16_t*/ complexf_t eq_buf[V27TER_EQUALIZER_LEN]; -#else - /*! \brief The scaling factor accessed by the AGC algorithm. */ - float agc_scaling; - /*! \brief The previous value of agc_scaling, needed to reuse old training. */ - float agc_scaling_save; - - /*! \brief The current delta factor for updating the equalizer coefficients. */ - float eq_delta; - /*! \brief The adaptive equalizer coefficients. */ - complexf_t eq_coeff[V27TER_EQUALIZER_LEN]; - /*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */ - complexf_t eq_coeff_save[V27TER_EQUALIZER_LEN]; - /*! \brief The equalizer signal buffer. */ - complexf_t eq_buf[V27TER_EQUALIZER_LEN]; -#endif - /*! \brief Integration variable for damping the Gardner algorithm tests. */ int gardner_integrate; /*! \brief Current step size of Gardner algorithm integration. */ diff --git a/libs/spandsp/src/spandsp/private/v27ter_tx.h b/libs/spandsp/src/spandsp/private/v27ter_tx.h index f9781aeb0f..18e27e1277 100644 --- a/libs/spandsp/src/spandsp/private/v27ter_tx.h +++ b/libs/spandsp/src/spandsp/private/v27ter_tx.h @@ -49,26 +49,24 @@ struct v27ter_tx_state_s #if defined(SPANDSP_USE_FIXED_POINT) /*! \brief The gain factor needed to achieve the specified output power at 2400bps. */ - int32_t gain_2400; + int16_t gain_2400; /*! \brief The gain factor needed to achieve the specified output power at 4800bps. */ - int32_t gain_4800; + int16_t gain_4800; + /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */ + complexi16_t rrc_filter[2*V27TER_TX_FILTER_STEPS]; #else /*! \brief The gain factor needed to achieve the specified output power at 2400bps. */ float gain_2400; /*! \brief The gain factor needed to achieve the specified output power at 4800bps. */ float gain_4800; -#endif - /*! \brief The route raised cosine (RRC) pulse shaping filter buffer. */ -#if defined(SPANDSP_USE_FIXED_POINT) - complexi16_t rrc_filter[2*V27TER_TX_FILTER_STEPS]; -#else + /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */ complexf_t rrc_filter[2*V27TER_TX_FILTER_STEPS]; #endif /*! \brief Current offset into the RRC pulse shaping filter buffer. */ int rrc_filter_step; /*! \brief The register for the training and data scrambler. */ - unsigned int scramble_reg; + uint32_t scramble_reg; /*! \brief A counter for the number of consecutive bits of repeating pattern through the scrambler. */ int scrambler_pattern_count; diff --git a/libs/spandsp/src/spandsp/t4_tx.h b/libs/spandsp/src/spandsp/t4_tx.h index 6ee4135b4b..3985e28f63 100644 --- a/libs/spandsp/src/spandsp/t4_tx.h +++ b/libs/spandsp/src/spandsp/t4_tx.h @@ -141,8 +141,8 @@ SPAN_DECLARE(void) t4_tx_set_header_info(t4_state_t *s, const char *info); the current time zone of the program's environment is used. \brief Set the header timezone. \param s The T.4 context. - \param info A POSIX timezone description string. */ -SPAN_DECLARE(void) t4_tx_set_header_tz(t4_state_t *s, const char *tzstring); + \param tz A time zone descriptor. */ +SPAN_DECLARE(void) t4_tx_set_header_tz(t4_state_t *s, tz_t *tz); /*! Set page header extends or overlays the image mode. \brief Set page header overlay mode. diff --git a/libs/spandsp/src/spandsp/v22bis.h b/libs/spandsp/src/spandsp/v22bis.h index 073fb7135a..440118c7cb 100644 --- a/libs/spandsp/src/spandsp/v22bis.h +++ b/libs/spandsp/src/spandsp/v22bis.h @@ -61,8 +61,6 @@ enum */ typedef struct v22bis_state_s v22bis_state_t; -extern const complexf_t v22bis_constellation[16]; - #if defined(__cplusplus) extern "C" { @@ -88,7 +86,11 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx_fillin(v22bis_state_t *s, int len); \brief Get a snapshot of the current equalizer coefficients. \param coeffs The vector of complex coefficients. \return The number of coefficients in the vector. */ +#if defined(SPANDSP_USE_FIXED_POINT) +SPAN_DECLARE(int) v22bis_rx_equalizer_state(v22bis_state_t *s, complexi16_t **coeffs); +#else SPAN_DECLARE(int) v22bis_rx_equalizer_state(v22bis_state_t *s, complexf_t **coeffs); +#endif /*! Get the current received carrier frequency. \param s The modem context. diff --git a/libs/spandsp/src/t30.c b/libs/spandsp/src/t30.c index 82724920c1..c301ceb0d4 100644 --- a/libs/spandsp/src/t30.c +++ b/libs/spandsp/src/t30.c @@ -58,9 +58,10 @@ #include "spandsp/v29tx.h" #include "spandsp/v27ter_rx.h" #include "spandsp/v27ter_tx.h" +#include "spandsp/timezone.h" #include "spandsp/t4_rx.h" #include "spandsp/t4_tx.h" -#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) | defined(SPANDSP_SUPPORT_T85) +#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) || defined(SPANDSP_SUPPORT_T85) #include "spandsp/t81_t82_arith_coding.h" #endif #if defined(SPANDSP_SUPPORT_T85) @@ -81,7 +82,8 @@ #include "spandsp/t30_logging.h" #include "spandsp/private/logging.h" -#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) | defined(SPANDSP_SUPPORT_T85) +#include "spandsp/private/timezone.h" +#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) || defined(SPANDSP_SUPPORT_T85) #include "spandsp/private/t81_t82_arith_coding.h" #endif #if defined(SPANDSP_SUPPORT_T85) @@ -781,11 +783,11 @@ static int send_next_ecm_frame(t30_state_t *s) } s->ecm_current_tx_frame = s->ecm_frames; } - if (s->ecm_current_tx_frame <= s->ecm_frames + 3) + if (s->ecm_current_tx_frame < s->ecm_frames + 3) { - /* We have sent all the FCD frames. Send some RCP frames. Three seems to be - a popular number, to minimise the risk of a bit error stopping the receiving - end from recognising the RCP. */ + /* We have sent all the FCD frames. Send three RCP frames, as per + T.4/A.1 and T.4/A.2. The repeats are to minimise the risk of a bit + error stopping the receiving end from recognising the RCP. */ s->ecm_current_tx_frame++; /* The RCP frame is an odd man out, as its a simple 1 byte control frame, but is specified to not have the final bit set. It doesn't @@ -794,7 +796,8 @@ static int send_next_ecm_frame(t30_state_t *s) frame[1] = CONTROL_FIELD_NON_FINAL_FRAME; frame[2] = T4_RCP; send_frame(s, frame, 3); - /* In case we are just after a CTC/CTR exchange, which kicked us back to long training */ + /* In case we are just after a CTC/CTR exchange, which kicked us back + to long training */ s->short_train = TRUE; return 0; } @@ -1974,6 +1977,8 @@ static int start_sending_document(t30_state_t *s) t4_tx_set_tx_encoding(&s->t4.tx, s->line_encoding); t4_tx_set_local_ident(&s->t4.tx, s->tx_info.ident); t4_tx_set_header_info(&s->t4.tx, s->header_info); + if (s->use_own_tz) + t4_tx_set_header_tz(&s->t4.tx, &s->tz); s->x_resolution = t4_tx_get_x_resolution(&s->t4.tx); s->y_resolution = t4_tx_get_y_resolution(&s->t4.tx); diff --git a/libs/spandsp/src/t30_api.c b/libs/spandsp/src/t30_api.c index b7a571989d..707f5fe44e 100644 --- a/libs/spandsp/src/t30_api.c +++ b/libs/spandsp/src/t30_api.c @@ -58,9 +58,10 @@ #include "spandsp/v29tx.h" #include "spandsp/v27ter_rx.h" #include "spandsp/v27ter_tx.h" +#include "spandsp/timezone.h" #include "spandsp/t4_rx.h" #include "spandsp/t4_tx.h" -#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) | defined(SPANDSP_SUPPORT_T85) +#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) || defined(SPANDSP_SUPPORT_T85) #include "spandsp/t81_t82_arith_coding.h" #endif #if defined(SPANDSP_SUPPORT_T85) @@ -81,7 +82,8 @@ #include "spandsp/t30_logging.h" #include "spandsp/private/logging.h" -#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) | defined(SPANDSP_SUPPORT_T85) +#include "spandsp/private/timezone.h" +#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) || defined(SPANDSP_SUPPORT_T85) #include "spandsp/private/t81_t82_arith_coding.h" #endif #if defined(SPANDSP_SUPPORT_T85) @@ -585,13 +587,6 @@ SPAN_DECLARE(int) t30_set_tx_page_header_info(t30_state_t *s, const char *info) } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(int) t30_set_tx_page_header_tz(t30_state_t *s, const char *tzstring) -{ - t4_tx_set_header_tz(&s->t4.tx, tzstring); - return 0; -} -/*- End of function --------------------------------------------------------*/ - SPAN_DECLARE(size_t) t30_get_tx_page_header_info(t30_state_t *s, char *info) { if (info) @@ -600,6 +595,18 @@ SPAN_DECLARE(size_t) t30_get_tx_page_header_info(t30_state_t *s, char *info) } /*- End of function --------------------------------------------------------*/ +SPAN_DECLARE(int) t30_set_tx_page_header_tz(t30_state_t *s, const char *tzstring) +{ + if (tz_init(&s->tz, tzstring)) + { + s->use_own_tz = TRUE; + t4_tx_set_header_tz(&s->t4.tx, &s->tz); + return 0; + } + return -1; +} +/*- End of function --------------------------------------------------------*/ + SPAN_DECLARE(const char *) t30_get_rx_country(t30_state_t *s) { return s->country; diff --git a/libs/spandsp/src/t30_logging.c b/libs/spandsp/src/t30_logging.c index 700c0db18d..52ab767dfc 100644 --- a/libs/spandsp/src/t30_logging.c +++ b/libs/spandsp/src/t30_logging.c @@ -58,9 +58,10 @@ #include "spandsp/v29tx.h" #include "spandsp/v27ter_rx.h" #include "spandsp/v27ter_tx.h" +#include "spandsp/timezone.h" #include "spandsp/t4_rx.h" #include "spandsp/t4_tx.h" -#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) | defined(SPANDSP_SUPPORT_T85) +#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) || defined(SPANDSP_SUPPORT_T85) #include "spandsp/t81_t82_arith_coding.h" #endif #if defined(SPANDSP_SUPPORT_T85) @@ -80,7 +81,8 @@ #include "spandsp/t30_logging.h" #include "spandsp/private/logging.h" -#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) | defined(SPANDSP_SUPPORT_T85) +#include "spandsp/private/timezone.h" +#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) || defined(SPANDSP_SUPPORT_T85) #include "spandsp/private/t81_t82_arith_coding.h" #endif #if defined(SPANDSP_SUPPORT_T85) diff --git a/libs/spandsp/src/t31.c b/libs/spandsp/src/t31.c index 5a23de1d2f..6839b0efcc 100644 --- a/libs/spandsp/src/t31.c +++ b/libs/spandsp/src/t31.c @@ -77,6 +77,7 @@ #if defined(SPANDSP_SUPPORT_V34) #include "spandsp/v34.h" #endif +#include "spandsp/timezone.h" #include "spandsp/t4_rx.h" #include "spandsp/t4_tx.h" #include "spandsp/t30.h" diff --git a/libs/spandsp/src/t38_gateway.c b/libs/spandsp/src/t38_gateway.c index 11760f9743..0626ac4086 100644 --- a/libs/spandsp/src/t38_gateway.c +++ b/libs/spandsp/src/t38_gateway.c @@ -71,9 +71,10 @@ #include "spandsp/v17rx.h" #include "spandsp/super_tone_rx.h" #include "spandsp/modem_connect_tones.h" +#include "spandsp/timezone.h" #include "spandsp/t4_rx.h" #include "spandsp/t4_tx.h" -#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) | defined(SPANDSP_SUPPORT_T85) +#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) || defined(SPANDSP_SUPPORT_T85) #include "spandsp/t81_t82_arith_coding.h" #endif #if defined(SPANDSP_SUPPORT_T85) @@ -108,7 +109,8 @@ #include "spandsp/private/modem_connect_tones.h" #include "spandsp/private/hdlc.h" #include "spandsp/private/fax_modems.h" -#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) | defined(SPANDSP_SUPPORT_T85) +#include "spandsp/private/timezone.h" +#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) || defined(SPANDSP_SUPPORT_T85) #include "spandsp/private/t81_t82_arith_coding.h" #endif #if defined(SPANDSP_SUPPORT_T85) diff --git a/libs/spandsp/src/t38_terminal.c b/libs/spandsp/src/t38_terminal.c index 64b30f4805..836210ca9f 100644 --- a/libs/spandsp/src/t38_terminal.c +++ b/libs/spandsp/src/t38_terminal.c @@ -61,9 +61,10 @@ #include "spandsp/v27ter_rx.h" #include "spandsp/v17tx.h" #include "spandsp/v17rx.h" +#include "spandsp/timezone.h" #include "spandsp/t4_rx.h" #include "spandsp/t4_tx.h" -#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) | defined(SPANDSP_SUPPORT_T85) +#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) || defined(SPANDSP_SUPPORT_T85) #include "spandsp/t81_t82_arith_coding.h" #endif #if defined(SPANDSP_SUPPORT_T85) @@ -86,7 +87,8 @@ #include "spandsp/t38_terminal.h" #include "spandsp/private/logging.h" -#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) | defined(SPANDSP_SUPPORT_T85) +#include "spandsp/private/timezone.h" +#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) || defined(SPANDSP_SUPPORT_T85) #include "spandsp/private/t81_t82_arith_coding.h" #endif #if defined(SPANDSP_SUPPORT_T85) diff --git a/libs/spandsp/src/t4_rx.c b/libs/spandsp/src/t4_rx.c index 131bfc0179..bc3389d7b4 100644 --- a/libs/spandsp/src/t4_rx.c +++ b/libs/spandsp/src/t4_rx.c @@ -82,6 +82,7 @@ #include "spandsp/logging.h" #include "spandsp/bit_operations.h" #include "spandsp/async.h" +#include "spandsp/timezone.h" #include "spandsp/t4_rx.h" #include "spandsp/t4_tx.h" #if defined(SPANDSP_SUPPORT_T85) diff --git a/libs/spandsp/src/t4_tx.c b/libs/spandsp/src/t4_tx.c index b2842a46d7..5d150348ba 100644 --- a/libs/spandsp/src/t4_tx.c +++ b/libs/spandsp/src/t4_tx.c @@ -1521,9 +1521,9 @@ SPAN_DECLARE(void) t4_tx_set_header_info(t4_state_t *s, const char *info) } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(void) t4_tx_set_header_tz(t4_state_t *s, const char *tzstring) +SPAN_DECLARE(void) t4_tx_set_header_tz(t4_state_t *s, tz_t *tz) { - s->tz = tz_init(s->tz, tzstring); + s->tz = tz; } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/src/v17rx.c b/libs/spandsp/src/v17rx.c index 89b7dc4c9a..62256eb3b4 100644 --- a/libs/spandsp/src/v17rx.c +++ b/libs/spandsp/src/v17rx.c @@ -126,13 +126,13 @@ enum #define ALPHA 0.99f #if defined(SPANDSP_USE_FIXED_POINTx) -#define SYNC_LOW_BAND_EDGE_COEFF_0 ((int)(FP_FACTOR*(2.0f*ALPHA*COS_LOW_BAND_EDGE))) -#define SYNC_LOW_BAND_EDGE_COEFF_1 ((int)(FP_FACTOR*(-ALPHA*ALPHA))) -#define SYNC_LOW_BAND_EDGE_COEFF_2 ((int)(FP_FACTOR*(-ALPHA*SIN_LOW_BAND_EDGE))) -#define SYNC_HIGH_BAND_EDGE_COEFF_0 ((int)(FP_FACTOR*(2.0f*ALPHA*COS_HIGH_BAND_EDGE))) -#define SYNC_HIGH_BAND_EDGE_COEFF_1 ((int)(FP_FACTOR*(-ALPHA*ALPHA))) -#define SYNC_HIGH_BAND_EDGE_COEFF_2 ((int)(FP_FACTOR*(-ALPHA*SIN_HIGH_BAND_EDGE))) -#define SYNC_MIXED_EDGES_COEFF_3 ((int)(FP_FACTOR*(-ALPHA*ALPHA*(SIN_HIGH_BAND_EDGE*COS_LOW_BAND_EDGE - SIN_LOW_BAND_EDGE*COS_HIGH_BAND_EDGE)))) +#define SYNC_LOW_BAND_EDGE_COEFF_0 FP_Q_6_10(2.0f*ALPHA*COS_LOW_BAND_EDGE) +#define SYNC_LOW_BAND_EDGE_COEFF_1 FP_Q_6_10(-ALPHA*ALPHA) +#define SYNC_LOW_BAND_EDGE_COEFF_2 FP_Q_6_10(-ALPHA*SIN_LOW_BAND_EDGE) +#define SYNC_HIGH_BAND_EDGE_COEFF_0 FP_Q_6_10(2.0f*ALPHA*COS_HIGH_BAND_EDGE) +#define SYNC_HIGH_BAND_EDGE_COEFF_1 FP_Q_6_10(-ALPHA*ALPHA) +#define SYNC_HIGH_BAND_EDGE_COEFF_2 FP_Q_6_10(-ALPHA*SIN_HIGH_BAND_EDGE) +#define SYNC_MIXED_EDGES_COEFF_3 FP_Q_6_10(-ALPHA*ALPHA*(SIN_HIGH_BAND_EDGE*COS_LOW_BAND_EDGE - SIN_LOW_BAND_EDGE*COS_HIGH_BAND_EDGE)) #else #define SYNC_LOW_BAND_EDGE_COEFF_0 (2.0f*ALPHA*COS_LOW_BAND_EDGE) #define SYNC_LOW_BAND_EDGE_COEFF_1 (-ALPHA*ALPHA) @@ -146,10 +146,10 @@ enum #if defined(SPANDSP_USE_FIXED_POINTx) static const int constellation_spacing[4] = { - ((int)(FP_FACTOR*1.414f), - ((int)(FP_FACTOR*2.0f)}, - ((int)(FP_FACTOR*2.828f)}, - ((int)(FP_FACTOR*4.0f)}, + FP_Q_6_10(1.414f), + FP_Q_6_10(2.0f), + FP_Q_6_10(2.828f), + FP_Q_6_10(4.0f) }; #else static const float constellation_spacing[4] = diff --git a/libs/spandsp/src/v22bis_rx.c b/libs/spandsp/src/v22bis_rx.c index 91b009ce85..199611a098 100644 --- a/libs/spandsp/src/v22bis_rx.c +++ b/libs/spandsp/src/v22bis_rx.c @@ -69,9 +69,9 @@ #include "spandsp/private/logging.h" #include "spandsp/private/v22bis.h" -#if defined(SPANDSP_USE_FIXED_POINTx) -#include "v22bis_rx_1200_floating_rrc.h" -#include "v22bis_rx_2400_floating_rrc.h" +#if defined(SPANDSP_USE_FIXED_POINT) +#include "v22bis_rx_1200_fixed_rrc.h" +#include "v22bis_rx_2400_fixed_rrc.h" #else #include "v22bis_rx_1200_floating_rrc.h" #include "v22bis_rx_2400_floating_rrc.h" @@ -79,6 +79,11 @@ #define ms_to_symbols(t) (((t)*600)/1000) +#if defined(SPANDSP_USE_FIXED_POINT) +#define FP_FACTOR 4096 +#define FP_SHIFT_FACTOR 12 +#endif + /*! The adaption rate coefficient for the equalizer */ #define EQUALIZER_DELTA 0.25f /*! The number of phase shifted coefficient set for the pulse shaping/bandpass filter */ @@ -167,24 +172,28 @@ void v22bis_report_status_change(v22bis_state_t *s, int status) } /*- End of function --------------------------------------------------------*/ +#if defined(SPANDSP_USE_FIXED_POINT) +SPAN_DECLARE(int) v22bis_rx_equalizer_state(v22bis_state_t *s, complexi16_t **coeffs) +#else SPAN_DECLARE(int) v22bis_rx_equalizer_state(v22bis_state_t *s, complexf_t **coeffs) +#endif { *coeffs = s->rx.eq_coeff; - return 2*V22BIS_EQUALIZER_LEN + 1; + return V22BIS_EQUALIZER_LEN; } /*- End of function --------------------------------------------------------*/ void v22bis_equalizer_coefficient_reset(v22bis_state_t *s) { /* Start with an equalizer based on everything being perfect */ -#if defined(SPANDSP_USE_FIXED_POINTx) - cvec_zeroi16(s->rx.eq_coeff, 2*V22BIS_EQUALIZER_LEN + 1); - s->rx.eq_coeff[V22BIS_EQUALIZER_LEN] = complex_seti16(3*FP_FACTOR, 0*FP_FACTOR); - s->rx.eq_delta = 32768.0f*EQUALIZER_DELTA/(2*V22BIS_EQUALIZER_LEN + 1); +#if defined(SPANDSP_USE_FIXED_POINT) + cvec_zeroi16(s->rx.eq_coeff, V22BIS_EQUALIZER_LEN); + s->rx.eq_coeff[V22BIS_EQUALIZER_PRE_LEN] = complex_seti16(FP_Q_4_12(3.0), FP_Q_4_12(0.0)); + s->rx.eq_delta = 32768.0f*EQUALIZER_DELTA/V22BIS_EQUALIZER_LEN; #else - cvec_zerof(s->rx.eq_coeff, 2*V22BIS_EQUALIZER_LEN + 1); - s->rx.eq_coeff[V22BIS_EQUALIZER_LEN] = complex_setf(3.0f, 0.0f); - s->rx.eq_delta = EQUALIZER_DELTA/(2*V22BIS_EQUALIZER_LEN + 1); + cvec_zerof(s->rx.eq_coeff, V22BIS_EQUALIZER_LEN); + s->rx.eq_coeff[V22BIS_EQUALIZER_PRE_LEN] = complex_setf(3.0f, 0.0f); + s->rx.eq_delta = EQUALIZER_DELTA/V22BIS_EQUALIZER_LEN; #endif } /*- End of function --------------------------------------------------------*/ @@ -192,63 +201,68 @@ void v22bis_equalizer_coefficient_reset(v22bis_state_t *s) static void equalizer_reset(v22bis_state_t *s) { v22bis_equalizer_coefficient_reset(s); -#if defined(SPANDSP_USE_FIXED_POINTx) - cvec_zeroi16(s->rx.eq_buf, V22BIS_EQUALIZER_MASK + 1); +#if defined(SPANDSP_USE_FIXED_POINT) + cvec_zeroi16(s->rx.eq_buf, V22BIS_EQUALIZER_LEN); #else - cvec_zerof(s->rx.eq_buf, V22BIS_EQUALIZER_MASK + 1); + cvec_zerof(s->rx.eq_buf, V22BIS_EQUALIZER_LEN); #endif s->rx.eq_put_step = 20 - 1; s->rx.eq_step = 0; } /*- End of function --------------------------------------------------------*/ -static complexf_t equalizer_get(v22bis_state_t *s) +#if defined(SPANDSP_USE_FIXED_POINT) +static __inline__ complexi16_t equalizer_get(v22bis_state_t *s) { - int i; - int p; - complexf_t z; - complexf_t z1; + complexi32_t zz; + complexi16_t z; /* Get the next equalized value. */ - z = complex_setf(0.0f, 0.0f); - p = s->rx.eq_step - 1; - for (i = 0; i < 2*V22BIS_EQUALIZER_LEN + 1; i++) - { - p = (p - 1) & V22BIS_EQUALIZER_MASK; - z1 = complex_mulf(&s->rx.eq_coeff[i], &s->rx.eq_buf[p]); - z = complex_addf(&z, &z1); - } + zz = cvec_circular_dot_prodi16(s->rx.eq_buf, s->rx.eq_coeff, V22BIS_EQUALIZER_LEN, s->rx.eq_step); + z.re = zz.re >> FP_SHIFT_FACTOR; + z.im = zz.im >> FP_SHIFT_FACTOR; return z; } +#else +static __inline__ complexf_t equalizer_get(v22bis_state_t *s) +{ + /* Get the next equalized value. */ + return cvec_circular_dot_prodf(s->rx.eq_buf, s->rx.eq_coeff, V22BIS_EQUALIZER_LEN, s->rx.eq_step); +} +#endif /*- End of function --------------------------------------------------------*/ -static void tune_equalizer(v22bis_state_t *s, const complexf_t *z, const complexf_t *target) +#if defined(SPANDSP_USE_FIXED_POINT) +static void tune_equalizer(v22bis_state_t *s, const complexi16_t *z, const complexi16_t *target) { - int i; - int p; - complexf_t ez; - complexf_t z1; + complexi16_t err; /* Find the x and y mismatch from the exact constellation position. */ - ez = complex_subf(target, z); - ez.re *= s->rx.eq_delta; - ez.im *= s->rx.eq_delta; - - p = s->rx.eq_step - 1; - for (i = 0; i < 2*V22BIS_EQUALIZER_LEN + 1; i++) - { - p = (p - 1) & V22BIS_EQUALIZER_MASK; - z1 = complex_conjf(&s->rx.eq_buf[p]); - z1 = complex_mulf(&ez, &z1); - s->rx.eq_coeff[i] = complex_addf(&s->rx.eq_coeff[i], &z1); - /* If we don't leak a little bit we seem to get some wandering adaption */ - s->rx.eq_coeff[i].re *= 0.9999f; - s->rx.eq_coeff[i].im *= 0.9999f; - } + err.re = target->re*FP_FACTOR - z->re; + err.im = target->im*FP_FACTOR - z->im; + err.re = ((int32_t) err.re*s->rx.eq_delta) >> 15; + err.im = ((int32_t) err.im*s->rx.eq_delta) >> 15; + cvec_circular_lmsi16(s->rx.eq_buf, s->rx.eq_coeff, V22BIS_EQUALIZER_LEN, s->rx.eq_step, &err); } +#else +static void tune_equalizer(v22bis_state_t *s, const complexf_t *z, const complexf_t *target) +{ + complexf_t err; + + /* Find the x and y mismatch from the exact constellation position. */ + err = complex_subf(target, z); + err.re *= s->rx.eq_delta; + err.im *= s->rx.eq_delta; + cvec_circular_lmsf(s->rx.eq_buf, s->rx.eq_coeff, V22BIS_EQUALIZER_LEN, s->rx.eq_step, &err); +} +#endif /*- End of function --------------------------------------------------------*/ +#if defined(SPANDSP_USE_FIXED_POINT) +static __inline__ void track_carrier(v22bis_state_t *s, const complexi16_t *z, const complexi16_t *target) +#else static __inline__ void track_carrier(v22bis_state_t *s, const complexf_t *z, const complexf_t *target) +#endif { float error; @@ -336,40 +350,69 @@ static int decode_baudx(v22bis_state_t *s, int nearest) static __inline__ void symbol_sync(v22bis_state_t *s) { +#if defined(SPANDSP_USE_FIXED_POINT) + int32_t p; + int32_t q; + complexi16_t zz; + complexi16_t a; + complexi16_t b; + complexi16_t c; +#else float p; float q; complexf_t zz; complexf_t a; complexf_t b; complexf_t c; +#endif + int aa[3]; + int i; + int j; /* This routine adapts the position of the half baud samples entering the equalizer. */ /* Perform a Gardner test for baud alignment on the three most recent samples. */ + for (i = 0, j = s->rx.eq_step; i < 3; i++) + { + if (--j < 0) + j = V22BIS_EQUALIZER_LEN - 1; + aa[i] = j; + } if (s->rx.sixteen_way_decisions) { - p = s->rx.eq_buf[(s->rx.eq_step - 3) & V22BIS_EQUALIZER_MASK].re - - s->rx.eq_buf[(s->rx.eq_step - 1) & V22BIS_EQUALIZER_MASK].re; - p *= s->rx.eq_buf[(s->rx.eq_step - 2) & V22BIS_EQUALIZER_MASK].re; + p = s->rx.eq_buf[aa[2]].re - s->rx.eq_buf[aa[0]].re; + p *= s->rx.eq_buf[aa[1]].re; - q = s->rx.eq_buf[(s->rx.eq_step - 3) & V22BIS_EQUALIZER_MASK].im - - s->rx.eq_buf[(s->rx.eq_step - 1) & V22BIS_EQUALIZER_MASK].im; - q *= s->rx.eq_buf[(s->rx.eq_step - 2) & V22BIS_EQUALIZER_MASK].im; + q = s->rx.eq_buf[aa[2]].im - s->rx.eq_buf[aa[0]].im; + q *= s->rx.eq_buf[aa[1]].im; } else { /* Rotate the points to the 45 degree positions, to maximise the effectiveness of the Gardner algorithm. This is particularly significant at the start of operation to pull things in quickly. */ - zz = complex_setf(0.894427, 0.44721f); - a = complex_mulf(&s->rx.eq_buf[(s->rx.eq_step - 3) & V22BIS_EQUALIZER_MASK], &zz); - b = complex_mulf(&s->rx.eq_buf[(s->rx.eq_step - 2) & V22BIS_EQUALIZER_MASK], &zz); - c = complex_mulf(&s->rx.eq_buf[(s->rx.eq_step - 1) & V22BIS_EQUALIZER_MASK], &zz); +#if defined(SPANDSP_USE_FIXED_POINT) + zz = complex_seti16(FP_Q_6_10(0.894427), FP_Q_6_10(0.44721f)); + a = complex_muli16(&s->rx.eq_buf[aa[2]], &zz); + b = complex_muli16(&s->rx.eq_buf[aa[1]], &zz); + c = complex_muli16(&s->rx.eq_buf[aa[0]], &zz); p = (a.re - c.re)*b.re; q = (a.im - c.im)*b.im; +#else + zz = complex_setf(0.894427, 0.44721f); + a = complex_mulf(&s->rx.eq_buf[aa[2]], &zz); + b = complex_mulf(&s->rx.eq_buf[aa[1]], &zz); + c = complex_mulf(&s->rx.eq_buf[aa[0]], &zz); + p = (a.re - c.re)*b.re; + q = (a.im - c.im)*b.im; +#endif } +#if defined(SPANDSP_USE_FIXED_POINT) + s->rx.gardner_integrate += (p + q > 0) ? s->rx.gardner_step : -s->rx.gardner_step; +#else s->rx.gardner_integrate += (p + q > 0.0f) ? s->rx.gardner_step : -s->rx.gardner_step; +#endif if (abs(s->rx.gardner_integrate) >= 16) { @@ -386,11 +429,21 @@ static __inline__ void symbol_sync(v22bis_state_t *s) } /*- End of function --------------------------------------------------------*/ +#if defined(SPANDSP_USE_FIXED_POINT) +static void process_half_baud(v22bis_state_t *s, const complexi16_t *sample) +#else static void process_half_baud(v22bis_state_t *s, const complexf_t *sample) +#endif { +#if defined(SPANDSP_USE_FIXED_POINT) + complexi16_t z; + complexi16_t zz; + const complexi16_t *target; +#else complexf_t z; complexf_t zz; const complexf_t *target; +#endif int re; int im; int nearest; @@ -403,7 +456,8 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample) /* Add a sample to the equalizer's circular buffer, but don't calculate anything at this time. */ s->rx.eq_buf[s->rx.eq_step] = z; - s->rx.eq_step = (s->rx.eq_step + 1) & V22BIS_EQUALIZER_MASK; + if (++s->rx.eq_step >= V22BIS_EQUALIZER_LEN) + s->rx.eq_step = 0; /* On alternate insertions we have a whole baud and must process it. */ if ((s->rx.baud_phase ^= 1)) @@ -416,6 +470,18 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample) /* Find the constellation point */ if (s->rx.sixteen_way_decisions) { +#if defined(SPANDSP_USE_FIXED_POINT) + re = (int) (z.re + FP_Q_6_10(3.0f)); + if (re > 5) + re = 5; + else if (re < 0) + re = 0; + im = (int) (z.im + FP_Q_6_10(3.0f)); + if (im > 5) + im = 5; + else if (im < 0) + im = 0; +#else re = (int) (z.re + 3.0f); if (re > 5) re = 5; @@ -426,13 +492,19 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample) im = 5; else if (im < 0) im = 0; +#endif nearest = space_map_v22bis[re][im]; } else { /* Rotate to 45 degrees, to make the slicing trivial */ +#if defined(SPANDSP_USE_FIXED_POINT) + zz = complex_seti16(FP_Q_4_12(0.894427), FP_Q_4_12(0.44721f)); + zz = complex_muli16(&z, &zz); +#else zz = complex_setf(0.894427, 0.44721f); zz = complex_mulf(&z, &zz); +#endif nearest = 0x01; if (zz.re < 0.0f) nearest |= 0x04; @@ -490,10 +562,7 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample) error could be higher. */ s->rx.gardner_step = 4; s->rx.pattern_repeats = 0; - if (s->calling_party) - s->rx.training = V22BIS_RX_TRAINING_STAGE_UNSCRAMBLED_ONES; - else - s->rx.training = V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200; + s->rx.training = (s->calling_party) ? V22BIS_RX_TRAINING_STAGE_UNSCRAMBLED_ONES : V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200; /* Be pessimistic and see what the handshake brings */ s->negotiated_bit_rate = 1200; break; @@ -527,14 +596,14 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample) /* It looks like the answering machine is sending us a clean unscrambled 11 or 00 */ if (s->bit_rate == 2400) { - /* Try to establish at 2400bps */ + /* Try to establish at 2400bps. */ span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting U0011 (S1) (Caller)\n"); s->tx.training = V22BIS_TX_TRAINING_STAGE_U0011; s->tx.training_count = 0; } else { - /* Only try to establish at 1200bps */ + /* Only try to establish at 1200bps. */ span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting S11 (1200) (Caller)\n"); s->tx.training = V22BIS_TX_TRAINING_STAGE_S11; s->tx.training_count = 0; @@ -547,14 +616,14 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample) break; case V22BIS_RX_TRAINING_STAGE_UNSCRAMBLED_ONES_SUSTAINING: /* Calling modem only */ - /* Wait for the end of the unscrambled ones at 1200bps */ + /* Wait for the end of the unscrambled ones at 1200bps. */ target = &v22bis_constellation[nearest]; track_carrier(s, &z, target); raw_bits = phase_steps[((nearest >> 2) - (s->rx.constellation_state >> 2)) & 3]; s->rx.constellation_state = nearest; if (raw_bits != s->rx.last_raw_bits) { - /* This looks like the end of the sustained initial unscrambled 11 or 00 */ + /* This looks like the end of the sustained initial unscrambled 11 or 00. */ s->tx.training_count = 0; s->tx.training = V22BIS_TX_TRAINING_STAGE_TIMED_S11; s->rx.training_count = 0; @@ -600,11 +669,11 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample) } if (s->rx.training_count >= ms_to_symbols(270)) { - /* If we haven't seen the S1 signal by now, we are committed to be in 1200bps mode */ + /* If we haven't seen the S1 signal by now, we are committed to be in 1200bps mode. */ if (s->calling_party) { span_log(&s->logging, SPAN_LOG_FLOW, "+++ Rx normal operation (1200)\n"); - /* The transmit side needs to sustain the scrambled ones for a timed period */ + /* The transmit side needs to sustain the scrambled ones for a timed period. */ s->tx.training_count = 0; s->tx.training = V22BIS_TX_TRAINING_STAGE_TIMED_S11; /* Normal reception starts immediately */ @@ -614,7 +683,7 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample) else { span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting S11 (1200) (Answerer)\n"); - /* The transmit side needs to sustain the scrambled ones for a timed period */ + /* The transmit side needs to sustain the scrambled ones for a timed period. */ s->tx.training_count = 0; s->tx.training = V22BIS_TX_TRAINING_STAGE_TIMED_S11; /* The receive side needs to wait a timed period, receiving scrambled ones, @@ -695,12 +764,21 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l { int i; int step; +#if defined(SPANDSP_USE_FIXED_POINT) + complexi16_t z; + complexi16_t zz; + complexi16_t sample; + int32_t ii; + int32_t qq; + float vv; +#else complexf_t z; complexf_t zz; - int32_t power; complexf_t sample; float ii; float qq; +#endif + int32_t power; for (i = 0; i < len; i++) { @@ -717,7 +795,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l if (s->calling_party) { #if defined(SPANDSP_USE_FIXED_POINT) - ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_2400_re[6], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step); + ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_2400_re[6], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step) >> 15; #else ii = vec_circular_dot_prodf(s->rx.rrc_filter, rx_pulseshaper_2400_re[6], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step); #endif @@ -725,7 +803,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l else { #if defined(SPANDSP_USE_FIXED_POINT) - ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_1200_re[6], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step); + ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_1200_re[6], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step) >> 15; #else ii = vec_circular_dot_prodf(s->rx.rrc_filter, rx_pulseshaper_1200_re[6], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step); #endif @@ -753,11 +831,25 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l { /* Only spend effort processing this data if the modem is not parked, after a training failure. */ +#if defined(SPANDSP_USE_FIXED_POINT) + z = dds_complexi16(&s->rx.carrier_phase, s->rx.carrier_phase_rate); +#else z = dds_complexf(&s->rx.carrier_phase, s->rx.carrier_phase_rate); +#endif if (s->rx.training == V22BIS_RX_TRAINING_STAGE_SYMBOL_ACQUISITION) { /* Only AGC during the initial symbol acquisition, and then lock the gain. */ +#if defined(SPANDSP_USE_FIXED_POINT) + vv = 0.18f*3.60f/sqrtf(power); + if (vv > 32767.0f) + s->rx.agc_scaling = 32767; + else if (vv > -32768.0f) + s->rx.agc_scaling = -32768; + else + s->rx.agc_scaling = vv; +#else s->rx.agc_scaling = 0.18f*3.60f/sqrtf(power); +#endif } /* Put things into the equalization buffer at T/2 rate. The Gardner algorithm will fiddle the step to align this with the symbols. */ @@ -774,8 +866,8 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l if (s->calling_party) { #if defined(SPANDSP_USE_FIXED_POINT) - ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_2400_re[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step); - qq = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_2400_im[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step); + ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_2400_re[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step) >> 15; + qq = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_2400_im[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step) >> 15; #else ii = vec_circular_dot_prodf(s->rx.rrc_filter, rx_pulseshaper_2400_re[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step); qq = vec_circular_dot_prodf(s->rx.rrc_filter, rx_pulseshaper_2400_im[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step); @@ -784,15 +876,20 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l else { #if defined(SPANDSP_USE_FIXED_POINT) - ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_1200_re[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step); - qq = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_1200_im[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step); + ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_1200_re[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step) >> 15; + qq = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_1200_im[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step) >> 15; #else ii = vec_circular_dot_prodf(s->rx.rrc_filter, rx_pulseshaper_1200_re[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step); qq = vec_circular_dot_prodf(s->rx.rrc_filter, rx_pulseshaper_1200_im[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step); #endif } +#if defined(SPANDSP_USE_FIXED_POINT) + sample.re = ((int32_t) ii*s->rx.agc_scaling) >> 10; + sample.im = ((int32_t) qq*s->rx.agc_scaling) >> 10; +#else sample.re = ii*s->rx.agc_scaling; sample.im = qq*s->rx.agc_scaling; +#endif /* Shift to baseband - since this is done in a full complex form, the result is clean, and requires no further filtering apart from the equalizer. */ @@ -817,7 +914,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx_fillin(v22bis_state_t *s, int len) return 0; for (i = 0; i < len; i++) { -#if defined(SPANDSP_USE_FIXED_POINTx) +#if defined(SPANDSP_USE_FIXED_POINT) dds_advance(&s->rx.carrier_phase, s->rx.carrier_phase_rate); #else dds_advancef(&s->rx.carrier_phase, s->rx.carrier_phase_rate); @@ -830,7 +927,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx_fillin(v22bis_state_t *s, int len) int v22bis_rx_restart(v22bis_state_t *s) { -#if defined(SPANDSP_USE_FIXED_POINTx) +#if defined(SPANDSP_USE_FIXED_POINT) vec_zeroi16(s->rx.rrc_filter, sizeof(s->rx.rrc_filter)/sizeof(s->rx.rrc_filter[0])); #else vec_zerof(s->rx.rrc_filter, sizeof(s->rx.rrc_filter)/sizeof(s->rx.rrc_filter[0])); @@ -861,8 +958,13 @@ int v22bis_rx_restart(v22bis_state_t *s) s->rx.training_error = 0.0f; s->rx.total_baud_timing_correction = 0; /* We want the carrier to pull in faster on the answerer side, as it has very little time to adapt. */ +#if defined(SPANDSP_USE_FIXED_POINT) + s->rx.carrier_track_i = (s->calling_party) ? 8000 : 40000; + s->rx.carrier_track_p = 8000000; +#else s->rx.carrier_track_i = (s->calling_party) ? 8000.0f : 40000.0f; s->rx.carrier_track_p = 8000000.0f; +#endif s->negotiated_bit_rate = 1200; diff --git a/libs/spandsp/src/v22bis_tx.c b/libs/spandsp/src/v22bis_tx.c index 39ad4dd240..7501800c3f 100644 --- a/libs/spandsp/src/v22bis_tx.c +++ b/libs/spandsp/src/v22bis_tx.c @@ -62,7 +62,7 @@ #include "spandsp/private/logging.h" #include "spandsp/private/v22bis.h" -#if defined(SPANDSP_USE_FIXED_POINTx) +#if defined(SPANDSP_USE_FIXED_POINT) #include "v22bis_tx_fixed_rrc.h" #else #include "v22bis_tx_floating_rrc.h" @@ -246,24 +246,28 @@ static const int phase_steps[4] = 1, 0, 2, 3 }; +#if defined(SPANDSP_USE_FIXED_POINT) +const complexi16_t v22bis_constellation[16] = +#else const complexf_t v22bis_constellation[16] = +#endif { - { 1.0f, 1.0f}, - { 3.0f, 1.0f}, /* 1200bps 00 */ - { 1.0f, 3.0f}, - { 3.0f, 3.0f}, - {-1.0f, 1.0f}, - {-1.0f, 3.0f}, /* 1200bps 01 */ - {-3.0f, 1.0f}, - {-3.0f, 3.0f}, - {-1.0f, -1.0f}, - {-3.0f, -1.0f}, /* 1200bps 10 */ - {-1.0f, -3.0f}, - {-3.0f, -3.0f}, - { 1.0f, -1.0f}, - { 1.0f, -3.0f}, /* 1200bps 11 */ - { 3.0f, -1.0f}, - { 3.0f, -3.0f} + { 1, 1}, + { 3, 1}, /* 1200bps 00 */ + { 1, 3}, + { 3, 3}, + {-1, 1}, + {-1, 3}, /* 1200bps 01 */ + {-3, 1}, + {-3, 3}, + {-1, -1}, + {-3, -1}, /* 1200bps 10 */ + {-1, -3}, + {-3, -3}, + { 1, -1}, + { 1, -3}, /* 1200bps 11 */ + { 3, -1}, + { 3, -3} }; static int fake_get_bit(void *user_data) @@ -308,9 +312,17 @@ static __inline__ int get_scrambled_bit(v22bis_state_t *s) } /*- End of function --------------------------------------------------------*/ +#if defined(SPANDSP_USE_FIXED_POINT) +static complexi16_t training_get(v22bis_state_t *s) +#else static complexf_t training_get(v22bis_state_t *s) +#endif { - complexf_t z; +#if defined(SPANDSP_USE_FIXED_POINT) + static const complexi16_t zero = {0, 0}; +#else + static const complexf_t zero = {0.0f, 0.0f}; +#endif int bits; /* V.22bis training sequence */ @@ -329,20 +341,17 @@ static complexf_t training_get(v22bis_state_t *s) case V22BIS_TX_TRAINING_STAGE_INITIAL_SILENCE: /* Silence */ s->tx.constellation_state = 0; - z = complex_setf(0.0f, 0.0f); - break; + return zero; case V22BIS_TX_TRAINING_STAGE_U11: /* Send continuous unscrambled ones at 1200bps (i.e. 270 degree phase steps). */ /* Only the answering modem sends unscrambled ones. It is the first thing exchanged between the modems. */ s->tx.constellation_state = (s->tx.constellation_state + phase_steps[3]) & 3; - z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01]; - break; + return v22bis_constellation[(s->tx.constellation_state << 2) | 0x01]; case V22BIS_TX_TRAINING_STAGE_U0011: /* Continuous unscrambled double dibit 00 11 at 1200bps. This is termed the S1 segment in the V.22bis spec. It is only sent to request or accept 2400bps mode, and lasts 100+-3ms. After this timed burst, we unconditionally change to sending scrambled ones at 1200bps. */ s->tx.constellation_state = (s->tx.constellation_state + phase_steps[3*(s->tx.training_count & 1)]) & 3; - z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01]; if (++s->tx.training_count >= ms_to_symbols(100)) { span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting S11 after U0011\n"); @@ -357,7 +366,7 @@ static complexf_t training_get(v22bis_state_t *s) s->tx.training = V22BIS_TX_TRAINING_STAGE_TIMED_S11; } } - break; + return v22bis_constellation[(s->tx.constellation_state << 2) | 0x01]; case V22BIS_TX_TRAINING_STAGE_TIMED_S11: /* A timed period of scrambled ones at 1200bps. */ if (++s->tx.training_count >= ms_to_symbols(756)) @@ -383,8 +392,7 @@ static complexf_t training_get(v22bis_state_t *s) bits = scramble(s, 1); bits = (bits << 1) | scramble(s, 1); s->tx.constellation_state = (s->tx.constellation_state + phase_steps[bits]) & 3; - z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01]; - break; + return v22bis_constellation[(s->tx.constellation_state << 2) | 0x01]; case V22BIS_TX_TRAINING_STAGE_S1111: /* Scrambled ones at 2400bps. We send a timed 200ms burst, and switch to normal operation at 2400bps */ bits = scramble(s, 1); @@ -392,7 +400,6 @@ static complexf_t training_get(v22bis_state_t *s) s->tx.constellation_state = (s->tx.constellation_state + phase_steps[bits]) & 3; bits = scramble(s, 1); bits = (bits << 1) | scramble(s, 1); - z = v22bis_constellation[(s->tx.constellation_state << 2) | bits]; if (++s->tx.training_count >= ms_to_symbols(200)) { /* We have completed training. Now handle some real work. */ @@ -402,18 +409,23 @@ static complexf_t training_get(v22bis_state_t *s) v22bis_report_status_change(s, SIG_STATUS_TRAINING_SUCCEEDED); s->tx.current_get_bit = s->get_bit; } - break; - case V22BIS_TX_TRAINING_STAGE_PARKED: - default: - z = complex_setf(0.0f, 0.0f); - break; + return v22bis_constellation[(s->tx.constellation_state << 2) | bits]; } - return z; + return zero; } /*- End of function --------------------------------------------------------*/ +#if defined(SPANDSP_USE_FIXED_POINT) +static complexi16_t getbaud(v22bis_state_t *s) +#else static complexf_t getbaud(v22bis_state_t *s) +#endif { +#if defined(SPANDSP_USE_FIXED_POINT) + static const complexi16_t zero = {0, 0}; +#else + static const complexf_t zero = {0.0f, 0.0f}; +#endif int bits; if (s->tx.training) @@ -428,7 +440,7 @@ static complexf_t getbaud(v22bis_state_t *s) if (s->tx.shutdown) { if (++s->tx.shutdown > 10) - return complex_setf(0.0f, 0.0f); + return zero; } /* The first two bits define the quadrant */ bits = get_scrambled_bit(s); @@ -450,11 +462,18 @@ static complexf_t getbaud(v22bis_state_t *s) SPAN_DECLARE_NONSTD(int) v22bis_tx(v22bis_state_t *s, int16_t amp[], int len) { +#if defined(SPANDSP_USE_FIXED_POINT) + complexi16_t v; + complexi32_t x; + complexi32_t z; + int16_t iamp; +#else + complexf_t v; complexf_t x; complexf_t z; - int i; - int sample; float famp; +#endif + int sample; if (s->tx.shutdown > 10) return 0; @@ -463,28 +482,41 @@ SPAN_DECLARE_NONSTD(int) v22bis_tx(v22bis_state_t *s, int16_t amp[], int len) if ((s->tx.baud_phase += 3) >= 40) { s->tx.baud_phase -= 40; - s->tx.rrc_filter[s->tx.rrc_filter_step] = - s->tx.rrc_filter[s->tx.rrc_filter_step + V22BIS_TX_FILTER_STEPS] = getbaud(s); + v = getbaud(s); + s->tx.rrc_filter_re[s->tx.rrc_filter_step] = v.re; + s->tx.rrc_filter_im[s->tx.rrc_filter_step] = v.im; if (++s->tx.rrc_filter_step >= V22BIS_TX_FILTER_STEPS) s->tx.rrc_filter_step = 0; } - /* Root raised cosine pulse shaping at baseband */ - x = complex_setf(0.0f, 0.0f); - for (i = 0; i < V22BIS_TX_FILTER_STEPS; i++) +#if defined(SPANDSP_USE_FIXED_POINT) + x.re = vec_circular_dot_prodi16(s->tx.rrc_filter_re, tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->tx.baud_phase], V22BIS_TX_FILTER_STEPS, s->tx.rrc_filter_step) >> 4; + x.im = vec_circular_dot_prodi16(s->tx.rrc_filter_im, tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->tx.baud_phase], V22BIS_TX_FILTER_STEPS, s->tx.rrc_filter_step) >> 4; + /* Now create and modulate the carrier */ + z = dds_complexi32(&s->tx.carrier_phase, s->tx.carrier_phase_rate); + iamp = (x.re*z.re - x.im*z.im) >> 15; + iamp = (int16_t) (((int32_t) iamp*s->tx.gain) >> 11); + if (s->tx.guard_phase_rate && (s->tx.rrc_filter_re[s->tx.rrc_filter_step] != 0 || s->tx.rrc_filter_im[s->tx.rrc_filter_step] != 0)) { - x.re += tx_pulseshaper[39 - s->tx.baud_phase][i]*s->tx.rrc_filter[i + s->tx.rrc_filter_step].re; - x.im += tx_pulseshaper[39 - s->tx.baud_phase][i]*s->tx.rrc_filter[i + s->tx.rrc_filter_step].im; + /* Add the guard tone */ + iamp += dds_mod(&s->tx.guard_phase, s->tx.guard_phase_rate, s->tx.guard_tone_gain, 0); } + /* Don't bother saturating. We should never clip. */ + amp[sample] = iamp; +#else + /* Root raised cosine pulse shaping at baseband */ + x.re = vec_circular_dot_prodf(s->tx.rrc_filter_re, tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->tx.baud_phase], V22BIS_TX_FILTER_STEPS, s->tx.rrc_filter_step); + x.im = vec_circular_dot_prodf(s->tx.rrc_filter_im, tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->tx.baud_phase], V22BIS_TX_FILTER_STEPS, s->tx.rrc_filter_step); /* Now create and modulate the carrier */ z = dds_complexf(&(s->tx.carrier_phase), s->tx.carrier_phase_rate); famp = (x.re*z.re - x.im*z.im)*s->tx.gain; - if (s->tx.guard_phase_rate && (s->tx.rrc_filter[s->tx.rrc_filter_step].re != 0.0f || s->tx.rrc_filter[s->tx.rrc_filter_step].im != 0.0f)) + if (s->tx.guard_phase_rate && (s->tx.rrc_filter_re[s->tx.rrc_filter_step] != 0.0f || s->tx.rrc_filter_im[s->tx.rrc_filter_step] != 0.0f)) { /* Add the guard tone */ - famp += dds_modf(&(s->tx.guard_phase), s->tx.guard_phase_rate, s->tx.guard_level, 0); + famp += dds_modf(&s->tx.guard_phase, s->tx.guard_phase_rate, s->tx.guard_tone_gain, 0); } /* Don't bother saturating. We should never clip. */ amp[sample] = (int16_t) lfastrintf(famp); +#endif } return sample; } @@ -492,34 +524,49 @@ SPAN_DECLARE_NONSTD(int) v22bis_tx(v22bis_state_t *s, int16_t amp[], int len) SPAN_DECLARE(void) v22bis_tx_power(v22bis_state_t *s, float power) { - float l; + float sig_power; + float guard_tone_power; + float sig_gain; + float guard_tone_gain; + /* If is there is a guard tone we need to scale down the signal power a bit, so the aggregate of the signal + and guard tone power is the specified power. */ if (s->tx.guard_phase_rate == dds_phase_ratef(550.0f)) { - l = 1.6f*powf(10.0f, (power - 1.0f - DBM0_MAX_POWER)/20.0f); - s->tx.gain = l*32768.0f/(TX_PULSESHAPER_GAIN*3.0f); - l = powf(10.0f, (power - 1.0f - 3.0f - DBM0_MAX_POWER)/20.0f); - s->tx.guard_level = l*32768.0f; + sig_power = power - 1.0f; + guard_tone_power = sig_power - 3.0f; } else if(s->tx.guard_phase_rate == dds_phase_ratef(1800.0f)) { - l = 1.6f*powf(10.0f, (power - 1.0f - 1.0f - DBM0_MAX_POWER)/20.0f); - s->tx.gain = l*32768.0f/(TX_PULSESHAPER_GAIN*3.0f); - l = powf(10.0f, (power - 1.0f - 6.0f - DBM0_MAX_POWER)/20.0f); - s->tx.guard_level = l*32768.0f; + sig_power = power - 0.55f; + guard_tone_power = sig_power - 6.0f; } else { - l = 1.6f*powf(10.0f, (power - DBM0_MAX_POWER)/20.0f); - s->tx.gain = l*32768.0f/(TX_PULSESHAPER_GAIN*3.0f); - s->tx.guard_level = 0; + sig_power = power; + guard_tone_power = -9999.0f; } + sig_gain = 0.4490f*powf(10.0f, (sig_power - DBM0_MAX_POWER)/20.0f)*32768.0f/TX_PULSESHAPER_GAIN; + guard_tone_gain = powf(10.0f, (guard_tone_power - DBM0_MAX_POWER)/20.0f)*32768.0f; +#if defined(SPANDSP_USE_FIXED_POINT) + s->tx.gain = (int16_t) sig_gain; + s->tx.guard_tone_gain = (int16_t) guard_tone_gain; +#else + s->tx.gain = sig_gain; + s->tx.guard_tone_gain = guard_tone_gain; +#endif } /*- End of function --------------------------------------------------------*/ static int v22bis_tx_restart(v22bis_state_t *s) { - cvec_zerof(s->tx.rrc_filter, sizeof(s->tx.rrc_filter)/sizeof(s->tx.rrc_filter[0])); +#if defined(SPANDSP_USE_FIXED_POINT) + vec_zeroi16(s->tx.rrc_filter_re, sizeof(s->tx.rrc_filter_re)/sizeof(s->tx.rrc_filter_re[0])); + vec_zeroi16(s->tx.rrc_filter_im, sizeof(s->tx.rrc_filter_im)/sizeof(s->tx.rrc_filter_im[0])); +#else + vec_zerof(s->tx.rrc_filter_re, sizeof(s->tx.rrc_filter_re)/sizeof(s->tx.rrc_filter_re[0])); + vec_zerof(s->tx.rrc_filter_im, sizeof(s->tx.rrc_filter_im)/sizeof(s->tx.rrc_filter_im[0])); +#endif s->tx.rrc_filter_step = 0; s->tx.scramble_reg = 0; s->tx.scrambler_pattern_count = 0; diff --git a/libs/spandsp/src/v27ter_rx.c b/libs/spandsp/src/v27ter_rx.c index 22ce185408..5ae87dc44d 100644 --- a/libs/spandsp/src/v27ter_rx.c +++ b/libs/spandsp/src/v27ter_rx.c @@ -44,6 +44,9 @@ #include "spandsp/telephony.h" #include "spandsp/logging.h" +#include "spandsp/fast_convert.h" +#include "spandsp/math_fixed.h" +#include "spandsp/saturated.h" #include "spandsp/complex.h" #include "spandsp/vector_float.h" #include "spandsp/complex_vector_float.h" @@ -62,9 +65,11 @@ #include "spandsp/private/v27ter_rx.h" #if defined(SPANDSP_USE_FIXED_POINT) +#define FP_SCALE FP_Q_6_10 #include "v27ter_rx_4800_fixed_rrc.h" #include "v27ter_rx_2400_fixed_rrc.h" #else +#define FP_SCALE(x) (x) #include "v27ter_rx_4800_floating_rrc.h" #include "v27ter_rx_2400_floating_rrc.h" #endif @@ -110,29 +115,19 @@ enum #if defined(SPANDSP_USE_FIXED_POINTx) static const complexi16_t v27ter_constellation[8] = -{ - {((int)(FP_FACTOR* 1.414f), ((int)(FP_FACTOR* 0.0f)}, /* 0deg */ - {((int)(FP_FACTOR* 1.0f), ((int)(FP_FACTOR* 1.0f)}, /* 45deg */ - {((int)(FP_FACTOR* 0.0f), ((int)(FP_FACTOR* 1.414f)}, /* 90deg */ - {((int)(FP_FACTOR*-1.0f), ((int)(FP_FACTOR* 1.0f)}, /* 135deg */ - {((int)(FP_FACTOR*-1.414f), ((int)(FP_FACTOR* 0.0f)}, /* 180deg */ - {((int)(FP_FACTOR*-1.0f), ((int)(FP_FACTOR*-1.0f)}, /* 225deg */ - {((int)(FP_FACTOR* 0.0f), ((int)(FP_FACTOR*-1.414f)}, /* 270deg */ - {((int)(FP_FACTOR* 1.0f), ((int)(FP_FACTOR*-1.0f)} /* 315deg */ -}; #else static const complexf_t v27ter_constellation[8] = -{ - { 1.414f, 0.0f}, /* 0deg */ - { 1.0f, 1.0f}, /* 45deg */ - { 0.0f, 1.414f}, /* 90deg */ - {-1.0f, 1.0f}, /* 135deg */ - {-1.414f, 0.0f}, /* 180deg */ - {-1.0f, -1.0f}, /* 225deg */ - { 0.0f, -1.414f}, /* 270deg */ - { 1.0f, -1.0f} /* 315deg */ -}; #endif +{ + {FP_SCALE( 1.414f), FP_SCALE( 0.0f)}, /* 0deg */ + {FP_SCALE( 1.0f), FP_SCALE( 1.0f)}, /* 45deg */ + {FP_SCALE( 0.0f), FP_SCALE( 1.414f)}, /* 90deg */ + {FP_SCALE(-1.0f), FP_SCALE( 1.0f)}, /* 135deg */ + {FP_SCALE(-1.414f), FP_SCALE( 0.0f)}, /* 180deg */ + {FP_SCALE(-1.0f), FP_SCALE(-1.0f)}, /* 225deg */ + {FP_SCALE( 0.0f), FP_SCALE(-1.414f)}, /* 270deg */ + {FP_SCALE( 1.0f), FP_SCALE(-1.0f)} /* 315deg */ +}; SPAN_DECLARE(float) v27ter_rx_carrier_frequency(v27ter_rx_state_t *s) { @@ -198,14 +193,14 @@ static void equalizer_restore(v27ter_rx_state_t *s) #if defined(SPANDSP_USE_FIXED_POINTx) cvec_copyi16(s->eq_coeff, s->eq_coeff_save, V27TER_EQUALIZER_LEN); cvec_zeroi16(s->eq_buf, V27TER_EQUALIZER_LEN); - s->eq_delta = 32768.0f*EQUALIZER_DELTA/V27TER_EQUALIZER_LEN); + s->eq_delta = 32768.0f*EQUALIZER_DELTA/V27TER_EQUALIZER_LEN; #else cvec_copyf(s->eq_coeff, s->eq_coeff_save, V27TER_EQUALIZER_LEN); cvec_zerof(s->eq_buf, V27TER_EQUALIZER_LEN); s->eq_delta = EQUALIZER_DELTA/V27TER_EQUALIZER_LEN; #endif - s->eq_put_step = (s->bit_rate == 4800) ? RX_PULSESHAPER_4800_COEFF_SETS*5/2 : RX_PULSESHAPER_2400_COEFF_SETS*20/(3*2); + s->eq_put_step = (s->bit_rate == 4800) ? (RX_PULSESHAPER_4800_COEFF_SETS*5/2 - 1) : (RX_PULSESHAPER_2400_COEFF_SETS*20/(3*2) - 1); s->eq_step = 0; } /*- End of function --------------------------------------------------------*/ @@ -214,13 +209,17 @@ static void equalizer_reset(v27ter_rx_state_t *s) { /* Start with an equalizer based on everything being perfect. */ #if defined(SPANDSP_USE_FIXED_POINTx) + static const complexi16_t x = {FP_SCALE(1.414f), FP_SCALE(0.0f)}; + cvec_zeroi16(s->eq_coeff, V27TER_EQUALIZER_LEN); - s->eq_coeff[V27TER_EQUALIZER_PRE_LEN + 1] = complex_seti16(1.414f*FP_FACTOR, 0); + s->eq_coeff[V27TER_EQUALIZER_PRE_LEN + 1] = x; cvec_zeroi16(s->eq_buf, V27TER_EQUALIZER_LEN); - s->eq_delta = 32768.0f*EQUALIZER_DELTA/V27TER_EQUALIZER_LEN); + s->eq_delta = 32768.0f*EQUALIZER_DELTA/V27TER_EQUALIZER_LEN; #else + static const complexf_t x = {1.414f, 0.0f}; + cvec_zerof(s->eq_coeff, V27TER_EQUALIZER_LEN); - s->eq_coeff[V27TER_EQUALIZER_PRE_LEN + 1] = complex_setf(1.414f, 0.0f); + s->eq_coeff[V27TER_EQUALIZER_PRE_LEN + 1] = x; cvec_zerof(s->eq_buf, V27TER_EQUALIZER_LEN); s->eq_delta = EQUALIZER_DELTA/V27TER_EQUALIZER_LEN; #endif @@ -324,8 +323,13 @@ static __inline__ int find_octant(complexf_t *z) if (abs_im > abs_re*0.4142136f && abs_im < abs_re*2.4142136f) { /* Split the space along the two axes. */ +#if defined(SPANDSP_USE_FIXED_POINTx) + b1 = (z->re < 0); + b2 = (z->im < 0); +#else b1 = (z->re < 0.0f); b2 = (z->im < 0.0f); +#endif bits = (b2 << 2) | ((b1 ^ b2) << 1) | 1; } else diff --git a/libs/spandsp/src/v27ter_tx.c b/libs/spandsp/src/v27ter_tx.c index bff8bb7071..f2673444ee 100644 --- a/libs/spandsp/src/v27ter_tx.c +++ b/libs/spandsp/src/v27ter_tx.c @@ -151,14 +151,14 @@ static complexf_t getbaud(v27ter_tx_state_t *s) #if defined(SPANDSP_USE_FIXED_POINT) static const complexi16_t constellation[8] = { - { 1414, 0000}, /* 0deg */ - { 1000, 1000}, /* 45deg */ - { 0000, 1414}, /* 90deg */ - {-1000, 1000}, /* 135deg */ - {-1414, 0000}, /* 180deg */ - {-1000, -1000}, /* 225deg */ - { 0000, -1414}, /* 270deg */ - { 1000, -1000} /* 315deg */ + {FP_Q_6_10( 1.414f), FP_Q_6_10( 0.0f)}, /* 0deg */ + {FP_Q_6_10( 1.0f), FP_Q_6_10( 1.0f)}, /* 45deg */ + {FP_Q_6_10( 0.0f), FP_Q_6_10( 1.414f)}, /* 90deg */ + {FP_Q_6_10(-1.0f), FP_Q_6_10( 1.0f)}, /* 135deg */ + {FP_Q_6_10(-1.414f), FP_Q_6_10( 0.0f)}, /* 180deg */ + {FP_Q_6_10(-1.0f), FP_Q_6_10(-1.0f)}, /* 225deg */ + {FP_Q_6_10( 0.0f), FP_Q_6_10(-1.414f)}, /* 270deg */ + {FP_Q_6_10( 1.0f), FP_Q_6_10(-1.0f)} /* 315deg */ }; static const complexi16_t zero = {0, 0}; #else diff --git a/libs/spandsp/tests/dtmf_rx_tests.c b/libs/spandsp/tests/dtmf_rx_tests.c index 01d96ea54e..e160bbf4ef 100644 --- a/libs/spandsp/tests/dtmf_rx_tests.c +++ b/libs/spandsp/tests/dtmf_rx_tests.c @@ -256,6 +256,7 @@ static void digit_status(void *data, int signal, int level, int delay) static int last_step = 0; static int first = TRUE; + //printf("Digit status %d %d %d\n", signal, level, delay); callback_hit = TRUE; len = step - last_step; if (data == (void *) 0x12345678) @@ -321,10 +322,14 @@ static void mitel_cm7291_side_1_tests(void) float rcfo; dtmf_rx_state_t *dtmf_state; awgn_state_t noise_source; + logging_state_t *logging; dtmf_state = dtmf_rx_init(NULL, NULL, NULL); if (use_dialtone_filter || max_forward_twist >= 0 || max_reverse_twist >= 0) dtmf_rx_parms(dtmf_state, use_dialtone_filter, max_forward_twist, max_reverse_twist, -99); + logging = dtmf_rx_get_logging_state(dtmf_state); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "DTMF-rx"); /* Test 1: Mitel's test 1 isn't really a test. Its a calibration step, which has no meaning here. */ @@ -627,10 +632,14 @@ static void mitel_cm7291_side_2_and_bellcore_tests(void) SNDFILE *inhandle; int frames; dtmf_rx_state_t *dtmf_state; + logging_state_t *logging; dtmf_state = dtmf_rx_init(NULL, NULL, NULL); if (use_dialtone_filter || max_forward_twist >= 0 || max_reverse_twist >= 0) dtmf_rx_parms(dtmf_state, use_dialtone_filter, max_forward_twist, max_reverse_twist, -99); + logging = dtmf_rx_get_logging_state(dtmf_state); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "DTMF-rx"); /* The remainder of the Mitel tape is the talk-off test */ /* Here we use the Bellcore test tapes (much tougher), in six @@ -694,10 +703,14 @@ static void dial_tone_tolerance_tests(void) dtmf_rx_state_t *dtmf_state; tone_gen_descriptor_t dial_tone_desc; tone_gen_state_t dial_tone; + logging_state_t *logging; dtmf_state = dtmf_rx_init(NULL, NULL, NULL); if (use_dialtone_filter || max_forward_twist >= 0 || max_reverse_twist >= 0) dtmf_rx_parms(dtmf_state, use_dialtone_filter, max_forward_twist, max_reverse_twist, -99); + logging = dtmf_rx_get_logging_state(dtmf_state); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "DTMF-rx"); /* Test dial tone tolerance */ printf("Test: Dial tone tolerance.\n"); @@ -742,6 +755,7 @@ static void callback_function_tests(void) int len; int sample; dtmf_rx_state_t *dtmf_state; + logging_state_t *logging; /* Test the callback mode for delivering detected digits */ printf("Test: Callback digit delivery mode.\n"); @@ -751,6 +765,9 @@ static void callback_function_tests(void) dtmf_state = dtmf_rx_init(NULL, digit_delivery, (void *) 0x12345678); if (use_dialtone_filter || max_forward_twist >= 0 || max_reverse_twist >= 0) dtmf_rx_parms(dtmf_state, use_dialtone_filter, max_forward_twist, max_reverse_twist, -99); + logging = dtmf_rx_get_logging_state(dtmf_state); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "DTMF-rx"); my_dtmf_gen_init(0.0f, DEFAULT_DTMF_TX_LEVEL, 0.0f, DEFAULT_DTMF_TX_LEVEL, DEFAULT_DTMF_TX_ON_TIME, DEFAULT_DTMF_TX_OFF_TIME); for (i = 1; i < 10; i++) @@ -778,6 +795,9 @@ static void callback_function_tests(void) dtmf_rx_set_realtime_callback(dtmf_state, digit_status, (void *) 0x12345678); if (use_dialtone_filter || max_forward_twist >= 0 || max_reverse_twist >= 0) dtmf_rx_parms(dtmf_state, use_dialtone_filter, max_forward_twist, max_reverse_twist, -99); + logging = dtmf_rx_get_logging_state(dtmf_state); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "DTMF-rx"); my_dtmf_gen_init(0.0f, DEFAULT_DTMF_TX_LEVEL, 0.0f, DEFAULT_DTMF_TX_LEVEL, DEFAULT_DTMF_TX_ON_TIME, DEFAULT_DTMF_TX_OFF_TIME); step = 0; @@ -813,19 +833,23 @@ static void decode_test(const char *test_file) int actual; int samples; int total; + logging_state_t *logging; dtmf_state = dtmf_rx_init(NULL, NULL, NULL); if (use_dialtone_filter || max_forward_twist >= 0 || max_reverse_twist >= 0) dtmf_rx_parms(dtmf_state, use_dialtone_filter, max_forward_twist, max_reverse_twist, -99); + logging = dtmf_rx_get_logging_state(dtmf_state); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + span_log_set_tag(logging, "DTMF-rx"); /* We will decode the audio from a file. */ - + if ((inhandle = sf_open_telephony_read(decode_test_file, 1)) == NULL) { fprintf(stderr, " Cannot open audio file '%s'\n", decode_test_file); exit(2); } - + total = 0; while ((samples = sf_readf_short(inhandle, amp, SAMPLES_PER_CHUNK)) > 0) { diff --git a/libs/spandsp/tests/fax_tests.c b/libs/spandsp/tests/fax_tests.c index 899091c611..4614ba1ffa 100644 --- a/libs/spandsp/tests/fax_tests.c +++ b/libs/spandsp/tests/fax_tests.c @@ -1,11 +1,11 @@ /* * SpanDSP - a series of DSP components for telephony * - * fax_tests.c + * fax_tests.c - Tests for the audio and T.38 FAX modules. * * Written by Steve Underwood * - * Copyright (C) 2003 Steve Underwood + * Copyright (C) 2005, 2006, 2009, 2010 Steve Underwood * * All rights reserved. * @@ -23,6 +23,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/*! \file */ + /*! \page fax_tests_page FAX tests \section fax_tests_page_sec_1 What does it do? \section fax_tests_page_sec_2 How does it work? @@ -33,11 +35,16 @@ #endif #include +#include #include -#include +#include #include #include +#include #include +#if !defined(_WIN32) +#include +#endif //#if defined(WITH_SPANDSP_INTERNALS) #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES @@ -206,6 +213,7 @@ int main(int argc, char *argv[]) time_t end_time; int scan_line_time; char *page_header_info; + char *page_header_tz; int opt; t30_state_t *t30; logging_state_t *logging; @@ -218,6 +226,7 @@ int main(int argc, char *argv[]) use_tep = FALSE; polled_mode = FALSE; page_header_info = NULL; + page_header_tz = NULL; reverse_flow = FALSE; use_transmit_on_idle = TRUE; use_receiver_not_ready = FALSE; @@ -226,7 +235,7 @@ int main(int argc, char *argv[]) noise_level = -99; scan_line_time = 0; supported_modems = T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17; - while ((opt = getopt(argc, argv, "ehH:i:I:lm:n:prRs:S:tTw:")) != -1) + while ((opt = getopt(argc, argv, "ehH:i:I:lm:n:prRs:S:tTw:z:")) != -1) { switch (opt) { @@ -278,6 +287,9 @@ int main(int argc, char *argv[]) case 'w': t30_state_to_wreck = atoi(optarg); break; + case 'z': + page_header_tz = optarg; + break; default: //usage(); exit(2); @@ -335,6 +347,8 @@ int main(int argc, char *argv[]) t30_set_tx_polled_sub_address(t30, "Polled sub-address"); t30_set_tx_selective_polling_address(t30, "Selective polling address"); t30_set_tx_page_header_info(t30, page_header_info); + if (page_header_tz) + t30_set_tx_page_header_tz(t30, page_header_tz); t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12); t30_set_ecm_capability(t30, use_ecm); t30_set_supported_t30_features(t30, diff --git a/libs/spandsp/tests/fax_tests.sh b/libs/spandsp/tests/fax_tests.sh index a798ff8a6a..41f6c2d72c 100755 --- a/libs/spandsp/tests/fax_tests.sh +++ b/libs/spandsp/tests/fax_tests.sh @@ -18,8 +18,8 @@ run_fax_test() { rm -f fax_tests_1.tif - echo -i ${FILE} ${OPTS} - ./fax_tests -i ${FILE} ${OPTS} >xyzzy 2>xyzzy2 + echo ./fax_tests ${OPTS} -i ${FILE} + ./fax_tests ${OPTS} -i ${FILE} >xyzzy 2>xyzzy2 RETVAL=$? if [ $RETVAL != 0 ] then diff --git a/libs/spandsp/tests/make_g168_css.c b/libs/spandsp/tests/make_g168_css.c index b8ce9016c6..850eb7e223 100644 --- a/libs/spandsp/tests/make_g168_css.c +++ b/libs/spandsp/tests/make_g168_css.c @@ -131,8 +131,8 @@ int main(int argc, char *argv[]) int16_t noise_sound[8830]; int16_t silence_sound[8192]; int i; - int outframes; int voiced_length; + int randy; double f; double pk; double ms; @@ -155,6 +155,18 @@ int main(int argc, char *argv[]) } printf("Generate C1\n"); + /* The sequence is + 48.62ms of voiced sound from table C.1 of G.168 + 200.0ms of pseudo-noise + 101.38ms of silence + The above is then repeated phase inverted. + + The voice comes straight from C.1, repeated enough times to + fill out the 48.62ms period - i.e. 16 copies of the sequence. + + The pseudo noise section is random numbers filtered by the spectral + pattern in Figure C.2 */ + /* The set of C1 voice samples is ready for use in the output file. */ voiced_length = sizeof(css_c1)/sizeof(css_c1[0]); for (i = 0; i < voiced_length; i++) @@ -208,13 +220,12 @@ int main(int argc, char *argv[]) #else scale = 0.0; #endif + randy = ((rand() >> 10) & 0x1) ? 1.0 : -1.0; #if defined(HAVE_FFTW3_H) - in[i][0] = ((rand() >> 10) & 0x1) ? 1.0 : -1.0; - in[i][0] *= pow(10.0, scale/20.0)*35.0; //305360 + in[i][0] = randy*pow(10.0, scale/20.0)*35.0; in[8192 - i][0] = -in[i][0]; #else - in[i].re = ((rand() >> 10) & 0x1) ? 1.0 : -1.0; - in[i].re *= pow(10.0, scale/20.0)*35.0; //305360 + in[i].re = randy*pow(10.0, scale/20.0)*35.0; in[8192 - i].re = -in[i].re; #endif } @@ -233,38 +244,34 @@ int main(int argc, char *argv[]) } pk = peak(noise_sound, 8192); ms = rms(noise_sound, 8192); - printf("Noise level = %.2fdB, crest factor = %.2fdB\n", rms_to_dbm0(ms), rms_to_db(pk/ms)); + printf("Filtered noise level = %.2fdB, crest factor = %.2fdB\n", rms_to_dbm0(ms), rms_to_db(pk/ms)); for (i = 0; i < 8192; i++) silence_sound[i] = 0.0; for (i = 0; i < 16; i++) - outframes = sf_writef_short(filehandle, voiced_sound, voiced_length); + sf_writef_short(filehandle, voiced_sound, voiced_length); printf("%d samples of voice\n", 16*voiced_length); - outframes = sf_writef_short(filehandle, noise_sound, 8192); - outframes = sf_writef_short(filehandle, noise_sound, C1_NOISE_SAMPLES - 8192); + sf_writef_short(filehandle, noise_sound, 8192); + sf_writef_short(filehandle, noise_sound, C1_NOISE_SAMPLES - 8192); printf("%d samples of noise\n", C1_NOISE_SAMPLES); - outframes = sf_writef_short(filehandle, silence_sound, C1_SILENCE_SAMPLES); + sf_writef_short(filehandle, silence_sound, C1_SILENCE_SAMPLES); printf("%d samples of silence\n", C1_SILENCE_SAMPLES); - /* Now phase invert the C1 set of voice samples. */ + /* Now phase invert the C1 set of samples. */ voiced_length = sizeof(css_c1)/sizeof(css_c1[0]); for (i = 0; i < voiced_length; i++) voiced_sound[i] = -css_c1[i]; - pk = peak(voiced_sound, voiced_length); - ms = rms(voiced_sound, voiced_length); - printf("Voiced level = %.2fdB, crest factor = %.2fdB\n", rms_to_dbm0(ms), rms_to_db(pk/ms)); - for (i = 0; i < 8192; i++) noise_sound[i] = -noise_sound[i]; for (i = 0; i < 16; i++) - outframes = sf_writef_short(filehandle, voiced_sound, voiced_length); + sf_writef_short(filehandle, voiced_sound, voiced_length); printf("%d samples of voice\n", 16*voiced_length); - outframes = sf_writef_short(filehandle, noise_sound, 8192); - outframes = sf_writef_short(filehandle, noise_sound, C1_NOISE_SAMPLES - 8192); + sf_writef_short(filehandle, noise_sound, 8192); + sf_writef_short(filehandle, noise_sound, C1_NOISE_SAMPLES - 8192); printf("%d samples of noise\n", C1_NOISE_SAMPLES); - outframes = sf_writef_short(filehandle, silence_sound, C1_SILENCE_SAMPLES); + sf_writef_short(filehandle, silence_sound, C1_SILENCE_SAMPLES); printf("%d samples of silence\n", C1_SILENCE_SAMPLES); if (sf_close(filehandle)) @@ -287,6 +294,21 @@ int main(int argc, char *argv[]) } printf("Generate C3\n"); + /* The sequence is + 72.69ms of voiced sound from table C.3 of G.168 + 200.0ms of pseudo-noise + 127.31ms of silence + The above is then repeated phase inverted. + + The voice comes straight from C.3, repeated enough times to + fill out the 72.69ms period - i.e. 14 copies of the sequence. + + The pseudo noise section is AWGN filtered by the spectral + pattern in Figure C.2. Since AWGN has the quality of being its + own Fourier transform, we can use an approach like the one above + for the C1 signal, using AWGN samples instead of randomly alternating + ones and zeros. */ + /* Take the supplied set of C3 voice samples. */ voiced_length = (sizeof(css_c3)/sizeof(css_c3[0])); for (i = 0; i < voiced_length; i++) @@ -300,37 +322,102 @@ int main(int argc, char *argv[]) noise_sound[i] = awgn(&noise_source); pk = peak(noise_sound, 8192); ms = rms(noise_sound, 8192); - printf("Noise level = %.2fdB, crest factor = %.2fdB\n", rms_to_dbm0(ms), rms_to_db(pk/ms)); + printf("Unfiltered noise level = %.2fdB, crest factor = %.2fdB\n", rms_to_dbm0(ms), rms_to_db(pk/ms)); + + /* Now filter them */ +#if defined(HAVE_FFTW3_H) + p = fftw_plan_dft_1d(8192, in, out, FFTW_BACKWARD, FFTW_ESTIMATE); +#else + p = fftw_create_plan(8192, FFTW_BACKWARD, FFTW_ESTIMATE); +#endif + for (i = 0; i < 8192; i++) + { +#if defined(HAVE_FFTW3_H) + in[i][0] = 0.0; + in[i][1] = 0.0; +#else + in[i].re = 0.0; + in[i].im = 0.0; +#endif + } + for (i = 1; i <= 3715; i++) + { + f = FAST_SAMPLE_RATE*i/8192.0; + +#if 1 + if (f < 50.0) + scale = -60.0; + else if (f < 100.0) + scale = scaling(f, 50.0, 100.0, -25.8, -12.8); + else if (f < 200.0) + scale = scaling(f, 100.0, 200.0, -12.8, 17.4); + else if (f < 215.0) + scale = scaling(f, 200.0, 215.0, 17.4, 17.8); + else if (f < 500.0) + scale = scaling(f, 215.0, 500.0, 17.8, 12.2); + else if (f < 1000.0) + scale = scaling(f, 500.0, 1000.0, 12.2, 7.2); + else if (f < 2850.0) + scale = scaling(f, 1000.0, 2850.0, 7.2, 0.0); + else if (f < 3600.0) + scale = scaling(f, 2850.0, 3600.0, 0.0, -2.0); + else if (f < 3660.0) + scale = scaling(f, 3600.0, 3660.0, -2.0, -20.0); + else if (f < 3680.0) + scale = scaling(f, 3600.0, 3680.0, -20.0, -30.0); + else + scale = -60.0; +#else + scale = 0.0; +#endif +#if defined(HAVE_FFTW3_H) + in[i][0] = noise_sound[i]*pow(10.0, scale/20.0)*0.0106; + in[8192 - i][0] = -in[i][0]; +#else + in[i].re = noise_sound[i]*pow(10.0, scale/20.0)*0.0106; + in[8192 - i].re = -in[i].re; +#endif + } +#if defined(HAVE_FFTW3_H) + fftw_execute(p); +#else + fftw_one(p, in, out); +#endif + for (i = 0; i < 8192; i++) + { +#if defined(HAVE_FFTW3_H) + noise_sound[i] = out[i][1]; +#else + noise_sound[i] = out[i].im; +#endif + } + pk = peak(noise_sound, 8192); + ms = rms(noise_sound, 8192); + printf("Filtered noise level = %.2fdB, crest factor = %.2fdB\n", rms_to_dbm0(ms), rms_to_db(pk/ms)); for (i = 0; i < 14; i++) - outframes = sf_writef_short(filehandle, voiced_sound, voiced_length); + sf_writef_short(filehandle, voiced_sound, voiced_length); printf("%d samples of voice\n", 14*voiced_length); - - outframes = sf_writef_short(filehandle, noise_sound, 8192); - outframes = sf_writef_short(filehandle, noise_sound, C3_NOISE_SAMPLES - 8192); + sf_writef_short(filehandle, noise_sound, 8192); + sf_writef_short(filehandle, noise_sound, C3_NOISE_SAMPLES - 8192); printf("%d samples of noise\n", C3_NOISE_SAMPLES); - outframes = sf_writef_short(filehandle, silence_sound, C3_SILENCE_SAMPLES); + sf_writef_short(filehandle, silence_sound, C3_SILENCE_SAMPLES); printf("%d samples of silence\n", C3_SILENCE_SAMPLES); - /* Now phase invert the set of voice samples. */ + /* Now phase invert the C3 set of samples. */ voiced_length = (sizeof(css_c3)/sizeof(css_c3[0])); for (i = 0; i < voiced_length; i++) voiced_sound[i] = -css_c3[i]; - pk = peak(voiced_sound, voiced_length); - ms = rms(voiced_sound, voiced_length); - printf("Voiced level = %.2fdB, crest factor = %.2fdB\n", rms_to_dbm0(ms), rms_to_db(pk/ms)); - - /* Now phase invert the set of noise samples. */ for (i = 0; i < 8192; i++) noise_sound[i] = -noise_sound[i]; for (i = 0; i < 14; i++) - outframes = sf_writef_short(filehandle, voiced_sound, voiced_length); - printf("%d samples of voice\n", 14*i); - outframes = sf_writef_short(filehandle, noise_sound, 8192); - outframes = sf_writef_short(filehandle, noise_sound, C3_NOISE_SAMPLES - 8192); + sf_writef_short(filehandle, voiced_sound, voiced_length); + printf("%d samples of voice\n", 14*voiced_length); + sf_writef_short(filehandle, noise_sound, 8192); + sf_writef_short(filehandle, noise_sound, C3_NOISE_SAMPLES - 8192); printf("%d samples of noise\n", C3_NOISE_SAMPLES); - outframes = sf_writef_short(filehandle, silence_sound, C3_SILENCE_SAMPLES); + sf_writef_short(filehandle, silence_sound, C3_SILENCE_SAMPLES); printf("%d samples of silence\n", C3_SILENCE_SAMPLES); if (sf_close(filehandle)) diff --git a/libs/spandsp/tests/regression_tests.sh b/libs/spandsp/tests/regression_tests.sh index 2a305531a6..a2b3649da0 100755 --- a/libs/spandsp/tests/regression_tests.sh +++ b/libs/spandsp/tests/regression_tests.sh @@ -334,6 +334,15 @@ then fi echo lpc10_tests completed OK +./math_fixed_tests >$STDOUT_DEST 2>$STDERR_DEST +RETVAL=$? +if [ $RETVAL != 0 ] +then + echo math_fixed_tests failed! + exit $RETVAL +fi +echo math_fixed_tests completed OK + ./modem_echo_tests >$STDOUT_DEST 2>$STDERR_DEST RETVAL=$? if [ $RETVAL != 0 ] diff --git a/libs/spandsp/tests/t4_tests.c b/libs/spandsp/tests/t4_tests.c index 3b3188dd08..8eb9c159a0 100644 --- a/libs/spandsp/tests/t4_tests.c +++ b/libs/spandsp/tests/t4_tests.c @@ -311,6 +311,7 @@ int main(int argc, char *argv[]) const char *in_file_name; const char *decode_file_name; const char *page_header_tz; + tz_t tz; int opt; int i; int bit_error_rate; @@ -678,7 +679,10 @@ int main(int argc, char *argv[]) else t4_tx_set_header_info(&send_state, NULL); if (page_header_tz && page_header_tz[0]) - t4_tx_set_header_tz(&send_state, page_header_tz); + { + if (tz_init(&tz, page_header_tz)) + t4_tx_set_header_tz(&send_state, &tz); + } //t4_tx_set_header_overlays_image(&send_state, overlay_page_headers); if (restart_pages && (sends & 1)) { diff --git a/libs/spandsp/tests/tone_generate_tests.c b/libs/spandsp/tests/tone_generate_tests.c index a98d4c15a6..469bfced5a 100644 --- a/libs/spandsp/tests/tone_generate_tests.c +++ b/libs/spandsp/tests/tone_generate_tests.c @@ -82,7 +82,7 @@ int main(int argc, char *argv[]) printf("Generated %d samples\n", len); if (len <= 0) break; - outframes = sf_writef_short(outhandle, amp, len); + sf_writef_short(outhandle, amp, len); } /* Try a different tone pair */ @@ -104,7 +104,7 @@ int main(int argc, char *argv[]) printf("Generated %d samples\n", len); if (len <= 0) break; - outframes = sf_writef_short(outhandle, amp, len); + sf_writef_short(outhandle, amp, len); } /* Try a different tone pair */ @@ -126,7 +126,7 @@ int main(int argc, char *argv[]) printf("Generated %d samples\n", len); if (len <= 0) break; - outframes = sf_writef_short(outhandle, amp, len); + sf_writef_short(outhandle, amp, len); } /* Try a single tone */ @@ -148,7 +148,7 @@ int main(int argc, char *argv[]) printf("Generated %d samples\n", len); if (len <= 0) break; - outframes = sf_writef_short(outhandle, amp, len); + sf_writef_short(outhandle, amp, len); } /* Try a single non-repeating tone */ @@ -170,7 +170,7 @@ int main(int argc, char *argv[]) printf("Generated %d samples\n", len); if (len <= 0) break; - outframes = sf_writef_short(outhandle, amp, len); + sf_writef_short(outhandle, amp, len); } /* Try a single non-repeating tone at 0dBm0 */ @@ -192,7 +192,7 @@ int main(int argc, char *argv[]) printf("Generated %d samples\n", len); if (len <= 0) break; - outframes = sf_writef_short(outhandle, amp, len); + sf_writef_short(outhandle, amp, len); } /* Try an AM modulated tone at a modest modulation level (25%) */ @@ -214,7 +214,7 @@ int main(int argc, char *argv[]) printf("Generated %d samples\n", len); if (len <= 0) break; - outframes = sf_writef_short(outhandle, amp, len); + sf_writef_short(outhandle, amp, len); } /* Try an AM modulated tone at maximum modulation level (100%) */ @@ -236,7 +236,7 @@ int main(int argc, char *argv[]) printf("Generated %d samples\n", len); if (len <= 0) break; - outframes = sf_writef_short(outhandle, amp, len); + sf_writef_short(outhandle, amp, len); } if (sf_close_telephony(outhandle)) diff --git a/libs/spandsp/tests/udptl.c b/libs/spandsp/tests/udptl.c index 553eba20e7..96071da55d 100644 --- a/libs/spandsp/tests/udptl.c +++ b/libs/spandsp/tests/udptl.c @@ -2,11 +2,12 @@ /* * SpanDSP - a series of DSP components for telephony * - * udptl.c + * udptl.c - An implementation of the UDPTL protocol defined in T.38, + * less the packet exchange part * * Written by Steve Underwood * - * Copyright (C) 2009 Steve Underwood + * Copyright (C) 2005 Steve Underwood * * All rights reserved. * @@ -62,15 +63,14 @@ static int decode_length(const uint8_t *buf, int limit, int *len, int *pvalue) } /*- End of function --------------------------------------------------------*/ -static int decode_open_type(const uint8_t *buf, int limit, int *len, const uint8_t ** p_object, int *p_num_octets) +static int decode_open_type(const uint8_t *buf, int limit, int *len, const uint8_t **p_object, int *p_num_octets) { int octet_cnt; int octet_idx; int stat; - int i; const uint8_t **pbuf; - for (octet_idx = 0, *p_num_octets = 0;; octet_idx += octet_cnt) + for (octet_idx = 0, *p_num_octets = 0; ; octet_idx += octet_cnt) { if ((stat = decode_length(buf, limit, len, &octet_cnt)) < 0) return -1; @@ -79,7 +79,6 @@ static int decode_open_type(const uint8_t *buf, int limit, int *len, const uint8 *p_num_octets += octet_cnt; pbuf = &p_object[octet_idx]; - i = 0; /* Make sure the buffer contains at least the number of bits requested */ if ((*len + octet_cnt) > limit) return -1; @@ -113,7 +112,7 @@ static int encode_length(uint8_t *buf, int *len, int value) return value; } /* Fragmentation */ - multiplier = (value < 0x10000) ? (value >> 14) : 4; + multiplier = (value < 0x10000) ? (value >> 14) : 4; /* Set the first 2 bits of the octet */ buf[(*len)++] = 0xC0 | multiplier; return multiplier << 14; @@ -134,7 +133,7 @@ static int encode_open_type(uint8_t *buf, int *len, const uint8_t *data, int num num_octets = 1; } /* Encode the open type */ - for (octet_idx = 0;; num_octets -= enclen, octet_idx += enclen) + for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen) { if ((enclen = encode_length(buf, len, num_octets)) < 0) return -1; @@ -192,7 +191,7 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len) if (msg_len > LOCAL_FAX_MAX_DATAGRAM) return -1; /* Update any missed slots in the buffer */ - for (i = s->rx_seq_no; seq_no > i; i++) + for (i = s->rx_seq_no; seq_no > i; i++) { x = i & UDPTL_BUF_MASK; s->rx[x].buf_len = -1; @@ -219,7 +218,7 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len) { if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0) return -1; - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) { if ((stat = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0) return -1; @@ -235,12 +234,12 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len) /* We received a later packet than we expected, so we need to check if we can fill in the gap from the secondary packets. */ /* Step through in reverse order, so we go oldest to newest */ - for (i = total_count; i > 0; i--) + for (i = total_count; i > 0; i--) { if (seq_no - i >= s->rx_seq_no) { /* This one wasn't seen before */ - /* Decode the secondary packet */ + /* Process the secondary packet */ #if defined(UDPTL_DEBUG) fprintf(stderr, "Secondary %d, len %d\n", seq_no - i, lengths[i - 1]); #endif @@ -286,7 +285,7 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len) s->rx[x].fec_entries = entries; /* Decode the elements */ - for (i = 0; i < entries; i++) + for (i = 0; i < entries; i++) { if ((stat = decode_open_type(buf, len, &ptr, &data, &s->rx[x].fec_len[i])) != 0) return -1; @@ -297,7 +296,7 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len) memcpy(s->rx[x].fec[i], data, s->rx[x].fec_len[i]); #if 0 fprintf(stderr, "FEC: "); - for (j = 0; j < s->rx[x].fec_len[i]; j++) + for (j = 0; j < s->rx[x].fec_len[i]; j++) fprintf(stderr, "%02X ", data[j]); fprintf(stderr, "\n"); #endif @@ -307,28 +306,32 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len) return -1; /* See if we can reconstruct anything which is missing */ /* TODO: this does not comprehensively hunt back and repair everything that is possible */ - for (l = x; l != ((x - (16 - span * entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK) + for (l = x; l != ((x - (16 - span*entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK) { if (s->rx[l].fec_len[0] <= 0) continue; - for (m = 0; m < s->rx[l].fec_entries; m++) + for (m = 0; m < s->rx[l].fec_entries; m++) { limit = (l + m) & UDPTL_BUF_MASK; - for (which = -1, k = (limit - s->rx[l].fec_span * s->rx[l].fec_entries) & UDPTL_BUF_MASK; k != limit; - k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK) + for (which = -1, k = (limit - s->rx[l].fec_span*s->rx[l].fec_entries) & UDPTL_BUF_MASK; + k != limit; + k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK) { if (s->rx[k].buf_len <= 0) - which = (which == -1) ? k : -2; + which = (which == -1) ? k : -2; } if (which >= 0) { /* Repairable */ - for (j = 0; j < s->rx[l].fec_len[m]; j++) + for (j = 0; j < s->rx[l].fec_len[m]; j++) { s->rx[which].buf[j] = s->rx[l].fec[m][j]; - for (k = (limit - s->rx[l].fec_span * s->rx[l].fec_entries) & UDPTL_BUF_MASK; k != limit; - k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK) - s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0; + for (k = (limit - s->rx[l].fec_span*s->rx[l].fec_entries) & UDPTL_BUF_MASK; + k != limit; + k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK) + { + s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0; + } } s->rx[which].buf_len = s->rx[l].fec_len[m]; repaired[which] = TRUE; @@ -336,7 +339,7 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len) } } /* Now play any new packets forwards in time */ - for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++) + for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++) { if (repaired[l]) { @@ -348,8 +351,8 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len) } } } - /* If packets are received out of sequence, we may have already processed this packet from the error - recovery information in a packet already received. */ + /* If packets are received out of sequence, we may have already processed this packet + from the error recovery information in a packet already received. */ if (seq_no >= s->rx_seq_no) { /* Decode the primary packet */ @@ -381,7 +384,7 @@ int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int /* UDPTL cannot cope with zero length messages, and our buffering for redundancy limits their maximum length. */ - if (msg_len < 1 || msg_len > LOCAL_FAX_MAX_DATAGRAM) + if (msg_len < 1 || msg_len > LOCAL_FAX_MAX_DATAGRAM) return -1; seq = s->tx_seq_no & 0xFFFF; @@ -427,7 +430,7 @@ int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int if (encode_length(buf, &len, entries) < 0) return -1; /* Encode the elements */ - for (i = 0; i < entries; i++) + for (i = 0; i < entries; i++) { j = (entry - i - 1) & UDPTL_BUF_MASK; if (encode_open_type(buf, &len, s->tx[j].buf, s->tx[j].buf_len) < 0) @@ -437,10 +440,10 @@ int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int case UDPTL_ERROR_CORRECTION_FEC: span = s->error_correction_span; entries = s->error_correction_entries; - if (seq < s->error_correction_span * s->error_correction_entries) + if (seq < s->error_correction_span*s->error_correction_entries) { /* In the initial stages, wind up the FEC smoothly */ - entries = seq / s->error_correction_span; + entries = seq/s->error_correction_span; if (seq < s->error_correction_span) span = 0; } @@ -453,24 +456,24 @@ int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int /* The number of entries is defined as a length, but will only ever be a small value. Treat it as such. */ buf[len++] = entries; - for (m = 0; m < entries; m++) + for (m = 0; m < entries; m++) { /* Make an XOR'ed entry the maximum length */ limit = (entry + m) & UDPTL_BUF_MASK; high_tide = 0; - for (i = (limit - span * entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK) + for (i = (limit - span*entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK) { if (high_tide < s->tx[i].buf_len) { - for (j = 0; j < high_tide; j++) + for (j = 0; j < high_tide; j++) fec[j] ^= s->tx[i].buf[j]; - for (; j < s->tx[i].buf_len; j++) + for ( ; j < s->tx[i].buf_len; j++) fec[j] = s->tx[i].buf[j]; high_tide = s->tx[i].buf_len; } else { - for (j = 0; j < s->tx[i].buf_len; j++) + for (j = 0; j < s->tx[i].buf_len; j++) fec[j] ^= s->tx[i].buf[j]; } } @@ -487,7 +490,10 @@ int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int } /*- End of function --------------------------------------------------------*/ -int udptl_set_error_correction(udptl_state_t *s, int ec_scheme, int span, int entries) +int udptl_set_error_correction(udptl_state_t *s, + int ec_scheme, + int span, + int entries) { switch (ec_scheme) { @@ -548,7 +554,12 @@ int udptl_get_far_max_datagram(udptl_state_t *s) } /*- End of function --------------------------------------------------------*/ -udptl_state_t *udptl_init(udptl_state_t *s, int ec_scheme, int span, int entries, udptl_rx_packet_handler_t rx_packet_handler, void *user_data) +udptl_state_t *udptl_init(udptl_state_t *s, + int ec_scheme, + int span, + int entries, + udptl_rx_packet_handler_t rx_packet_handler, + void *user_data) { int i; @@ -571,7 +582,7 @@ udptl_state_t *udptl_init(udptl_state_t *s, int ec_scheme, int span, int entries memset(&s->rx, 0, sizeof(s->rx)); memset(&s->tx, 0, sizeof(s->tx)); - for (i = 0; i <= UDPTL_BUF_MASK; i++) + for (i = 0; i <= UDPTL_BUF_MASK; i++) { s->rx[i].buf_len = -1; s->tx[i].buf_len = -1; diff --git a/libs/spandsp/tests/v17_tests.c b/libs/spandsp/tests/v17_tests.c index 40d4a3de25..ddf1b27104 100644 --- a/libs/spandsp/tests/v17_tests.c +++ b/libs/spandsp/tests/v17_tests.c @@ -119,17 +119,17 @@ static void reporter(void *user_data, int reason, bert_results_t *results) static void v17_rx_status(void *user_data, int status) { - v17_rx_state_t *rx; + v17_rx_state_t *s; int i; int len; complexf_t *coeffs; - + printf("V.17 rx status is %s (%d)\n", signal_status_to_str(status), status); - rx = (v17_rx_state_t *) user_data; + s = (v17_rx_state_t *) user_data; switch (status) { case SIG_STATUS_TRAINING_SUCCEEDED: - len = v17_rx_equalizer_state(rx, &coeffs); + len = v17_rx_equalizer_state(s, &coeffs); printf("Equalizer:\n"); for (i = 0; i < len; i++) printf("%3d (%15.5f, %15.5f) -> %15.5f\n", i, coeffs[i].re, coeffs[i].im, powerf(&coeffs[i])); @@ -140,15 +140,12 @@ static void v17_rx_status(void *user_data, int status) static void v17putbit(void *user_data, int bit) { - v17_rx_state_t *rx; - if (bit < 0) { v17_rx_status(user_data, bit); return; } - rx = (v17_rx_state_t *) user_data; if (decode_test_file) printf("Rx bit %d - %d\n", rx_bits++, bit); else diff --git a/libs/spandsp/tests/v18_tests.c b/libs/spandsp/tests/v18_tests.c index d6465fe21a..1666ce96a1 100644 --- a/libs/spandsp/tests/v18_tests.c +++ b/libs/spandsp/tests/v18_tests.c @@ -228,7 +228,6 @@ static int test_x_06(void) char dtmf[1024]; char result[1024]; const char *ref; - int len; int i; /* III.5.4.5.6 DTMF character conversion */ @@ -237,14 +236,14 @@ static int test_x_06(void) msg[127] = '\0'; printf("%s\n", msg); - len = v18_encode_dtmf(NULL, dtmf, msg); + v18_encode_dtmf(NULL, dtmf, msg); printf("%s\n", dtmf); - len = v18_decode_dtmf(NULL, result, dtmf); + v18_decode_dtmf(NULL, result, dtmf); ref = "\b \n\n\n?\n\n\n %+().+,-.0123456789:;(=)" - "?XABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ" - " abcdefghijklmnopqrstuvwxyzæøå \b"; + "?XABCDEFGHIJKLMNOPQRSTUVWXYZ\xC6\xD8\xC5" + " abcdefghijklmnopqrstuvwxyz\xE6\xF8\xE5 \b"; printf("Result:\n%s\n", result); printf("Reference result:\n%s\n", ref); diff --git a/libs/spandsp/tests/v22bis_tests.c b/libs/spandsp/tests/v22bis_tests.c index 3f47d61843..f1527a4c91 100644 --- a/libs/spandsp/tests/v22bis_tests.c +++ b/libs/spandsp/tests/v22bis_tests.c @@ -224,6 +224,7 @@ int main(int argc, char *argv[]) int log_audio; int channel_codec; int rbs_pattern; + int guard_tone_option; int opt; channel_codec = MUNGE_CODEC_NONE; @@ -234,8 +235,9 @@ int main(int argc, char *argv[]) noise_level = -70; signal_level = -13; bits_per_test = 50000; + guard_tone_option = V22BIS_GUARD_TONE_1800HZ; log_audio = FALSE; - while ((opt = getopt(argc, argv, "b:B:c:d:glm:n:r:s:")) != -1) + while ((opt = getopt(argc, argv, "b:B:c:d:gG:lm:n:r:s:")) != -1) { switch (opt) { @@ -264,6 +266,9 @@ int main(int argc, char *argv[]) exit(2); #endif break; + case 'G': + guard_tone_option = atoi(optarg); + break; case 'l': log_audio = TRUE; break; @@ -309,7 +314,7 @@ int main(int argc, char *argv[]) for (i = 0; i < 2; i++) { - endpoint[i].v22bis = v22bis_init(NULL, test_bps, V22BIS_GUARD_TONE_1800HZ, (i == 0), v22bis_getbit, &endpoint[i], v22bis_putbit, &endpoint[i]); + endpoint[i].v22bis = v22bis_init(NULL, test_bps, guard_tone_option, (i == 0), v22bis_getbit, &endpoint[i], v22bis_putbit, &endpoint[i]); v22bis_tx_power(endpoint[i].v22bis, signal_level); /* Move the carrier off a bit */ endpoint[i].v22bis->tx.carrier_phase_rate = dds_phase_ratef((i == 0) ? 1207.0f : 2407.0f); @@ -420,7 +425,7 @@ int main(int argc, char *argv[]) } if (log_audio) { - if (sf_close_telephony(outhandle) != 0) + if (sf_close_telephony(outhandle)) { fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME); exit(2); diff --git a/libs/spandsp/tests/v8_tests.c b/libs/spandsp/tests/v8_tests.c index 0f3ee358ba..35f1eb20e5 100644 --- a/libs/spandsp/tests/v8_tests.c +++ b/libs/spandsp/tests/v8_tests.c @@ -514,7 +514,6 @@ int main(int argc, char *argv[]) { int16_t amp[SAMPLES_PER_CHUNK]; int samples; - int remnant; int caller_available_modulations; int answerer_available_modulations; SNDFILE *inhandle; @@ -622,10 +621,10 @@ int main(int argc, char *argv[]) while ((samples = sf_readf_short(inhandle, amp, SAMPLES_PER_CHUNK))) { - remnant = v8_rx(v8_caller, amp, samples); - remnant = v8_rx(v8_answerer, amp, samples); - remnant = v8_tx(v8_caller, amp, samples); - remnant = v8_tx(v8_answerer, amp, samples); + v8_rx(v8_caller, amp, samples); + v8_rx(v8_answerer, amp, samples); + v8_tx(v8_caller, amp, samples); + v8_tx(v8_answerer, amp, samples); } /*endwhile*/ diff --git a/libs/spandsp/tests/vector_int_tests.c b/libs/spandsp/tests/vector_int_tests.c index 53f0b07949..1b0aa309c1 100644 --- a/libs/spandsp/tests/vector_int_tests.c +++ b/libs/spandsp/tests/vector_int_tests.c @@ -110,15 +110,11 @@ static int test_vec_min_maxi16(void) int32_t za; int32_t zb; int16_t x[99]; - int16_t y[99]; int16_t outa[2]; int16_t outb[2]; for (i = 0; i < 99; i++) - { x[i] = rand(); - y[i] = rand(); - } x[42] = -32768; za = vec_min_maxi16_dumb(x, 99, outa); diff --git a/libs/srtp/Makefile.am b/libs/srtp/Makefile.am index 4015ef977e..a238b660ee 100644 --- a/libs/srtp/Makefile.am +++ b/libs/srtp/Makefile.am @@ -1,4 +1,4 @@ -AUTOMAKE_OPTS= gnu +AUTOMAKE_OPTIONS = gnu NAME=srtp AM_CFLAGS = $(new_AM_CFLAGS) -I./src -Icrypto/include -I$(srcdir)/include -I$(srcdir)/crypto/include diff --git a/libs/srtp/test/Makefile.am b/libs/srtp/test/Makefile.am index 05624ba7e9..2651f2714f 100644 --- a/libs/srtp/test/Makefile.am +++ b/libs/srtp/test/Makefile.am @@ -1,4 +1,4 @@ -AUTOMAKE_OPTS= gnu +AUTOMAKE_OPTIONS = gnu AM_CFLAGS = $(new_AM_CFLAGS) -I$(top_srcdir)/include -I$(top_srcdir)/crypto/include AM_CPPFLAGS = $(AM_CFLAGS) AM_LDFLAGS = $(new_AM_LDFLAGS) -L$(srcdir) -lsrtp diff --git a/libs/stfu/stfu.c b/libs/stfu/stfu.c index 75a659d894..0bd42a7d4a 100644 --- a/libs/stfu/stfu.c +++ b/libs/stfu/stfu.c @@ -389,9 +389,9 @@ static void stfu_n_swap(stfu_instance_t *i) i->ready = 1; - i->in_queue = last_out; - i->out_queue = last_old; - i->old_queue = last_in; + i->in_queue = last_old; + i->out_queue = last_in; + i->old_queue = last_out; i->in_queue->array_len = 0; i->out_queue->wr_len = 0; @@ -600,7 +600,7 @@ static int stfu_n_find_any_frame(stfu_instance_t *in, stfu_queue_t *queue, stfu_ } -static int stfu_n_find_frame(stfu_instance_t *in, stfu_queue_t *queue, uint32_t ts, stfu_frame_t **r_frame) +static int stfu_n_find_frame(stfu_instance_t *in, stfu_queue_t *queue, uint32_t min_ts, uint32_t max_ts, stfu_frame_t **r_frame) { uint32_t i = 0; stfu_frame_t *frame = NULL; @@ -612,7 +612,7 @@ static int stfu_n_find_frame(stfu_instance_t *in, stfu_queue_t *queue, uint32_t for(i = 0; i < queue->array_size; i++) { frame = &queue->array[i]; - if (frame->ts == ts) { + if (frame->ts == max_ts || (frame->ts > min_ts && frame->ts < max_ts)) { if (r_frame) { *r_frame = frame; queue->last_index = i; @@ -662,20 +662,24 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i) i->cur_ts = i->cur_ts + i->samples_per_packet; } - found = stfu_n_find_frame(i, i->out_queue, i->cur_ts, &rframe); + found = stfu_n_find_frame(i, i->out_queue, i->last_wr_ts, i->cur_ts, &rframe); if (found) { if (i->out_queue->array_len) { i->out_queue->array_len--; } } else { - found = stfu_n_find_frame(i, i->in_queue, i->cur_ts, &rframe); + found = stfu_n_find_frame(i, i->in_queue, i->last_wr_ts, i->cur_ts, &rframe); if (!found) { - found = stfu_n_find_frame(i, i->old_queue, i->cur_ts, &rframe); + found = stfu_n_find_frame(i, i->old_queue, i->last_wr_ts, i->cur_ts, &rframe); } } + if (found) { + i->cur_ts = rframe->ts; + } + if (i->sync_out) { if (!found) { if ((found = stfu_n_find_any_frame(i, i->out_queue, &rframe))) { diff --git a/libs/unimrcp/Makefile.am b/libs/unimrcp/Makefile.am index 0421198eb9..0719b6bf78 100644 --- a/libs/unimrcp/Makefile.am +++ b/libs/unimrcp/Makefile.am @@ -12,7 +12,7 @@ EXTRA_DIST = bootstrap AUTOMAKE_OPTIONS = foreign MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure $(AUX_DIST) -ACLOCAL = aclocal -I $(macrodir) +ACLOCAL = aclocal SUBDIRS = build conf data libs modules plugins platforms if TEST_SUITES diff --git a/libs/win32/Download LAME.2008.vcproj b/libs/win32/Download LAME.2008.vcproj index 3deff23580..41b58f1a11 100644 --- a/libs/win32/Download LAME.2008.vcproj +++ b/libs/win32/Download LAME.2008.vcproj @@ -76,8 +76,8 @@ diff --git a/libs/win32/Download LAME.2010.vcxproj b/libs/win32/Download LAME.2010.vcxproj index 0715177aff..2411534cd7 100644 --- a/libs/win32/Download LAME.2010.vcxproj +++ b/libs/win32/Download LAME.2010.vcxproj @@ -66,13 +66,13 @@ Document Downloading Lame. - if not exist "$(ProjectDir)..\lame-3.97" cscript /nologo "$(ProjectDir)util.vbs" GetUnzip http://files.freeswitch.org/downloads/libs/lame-3.97.tar.gz "$(ProjectDir).." + if not exist "$(ProjectDir)..\lame-3.98.4" cscript /nologo "$(ProjectDir)util.vbs" GetUnzip http://files.freeswitch.org/downloads/libs/lame-3.98.4.tar.gz "$(ProjectDir).." - $(ProjectDir)..\lame-3.97;%(Outputs) + $(ProjectDir)..\lame-3.98.4;%(Outputs) Downloading Lame. - if not exist "$(ProjectDir)..\lame-3.97" cscript /nologo "$(ProjectDir)util.vbs" GetUnzip http://files.freeswitch.org/downloads/libs/lame-3.97.tar.gz "$(ProjectDir).." + if not exist "$(ProjectDir)..\lame-3.98.4" cscript /nologo "$(ProjectDir)util.vbs" GetUnzip http://files.freeswitch.org/downloads/libs/lame-3.98.4.tar.gz "$(ProjectDir).." - $(ProjectDir)..\lame-3.97;%(Outputs) + $(ProjectDir)..\lame-3.98.4;%(Outputs) diff --git a/libs/win32/iksemel/iksemel.2008.vcproj b/libs/win32/iksemel/iksemel.2008.vcproj index 57c2dd9874..f0219f38e1 100644 --- a/libs/win32/iksemel/iksemel.2008.vcproj +++ b/libs/win32/iksemel/iksemel.2008.vcproj @@ -44,8 +44,71 @@ + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/libs/win32/iksemel/iksemel.2010.vcxproj b/libs/win32/iksemel/iksemel.2010.vcxproj index d3c870eb13..1eed5afb0c 100644 --- a/libs/win32/iksemel/iksemel.2010.vcxproj +++ b/libs/win32/iksemel/iksemel.2010.vcxproj @@ -69,8 +69,8 @@ Disabled - ..\..\iksemel\include;.;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions) + ..\..\iksemel\include;.;..\..\openssl-1.0.0a\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;HAVE_SSL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -79,8 +79,8 @@ - ..\..\iksemel\include;.;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions) + ..\..\iksemel\include;.;..\..\openssl-1.0.0a\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;HAVE_SSL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions) MultiThreadedDLL TurnOffAllWarnings @@ -91,8 +91,8 @@ Disabled - ..\..\iksemel\include;.;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions) + ..\..\iksemel\include;.;..\..\openssl-1.0.0a\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;HAVE_SSL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -104,8 +104,8 @@ X64 - ..\..\iksemel\include;.;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions) + ..\..\iksemel\include;.;..\..\openssl-1.0.0a\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;HAVE_SSL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions) MultiThreadedDLL TurnOffAllWarnings diff --git a/libs/win32/libmp3lame/libmp3lame.2010.vcxproj b/libs/win32/libmp3lame/libmp3lame.2010.vcxproj index 8cb8f570ea..d88f17efd6 100644 --- a/libs/win32/libmp3lame/libmp3lame.2010.vcxproj +++ b/libs/win32/libmp3lame/libmp3lame.2010.vcxproj @@ -67,7 +67,7 @@ /GAy /QIfdiv /QI0f %(AdditionalOptions) MaxSpeed - .;..\..\lame-3.97;..\..\lame-3.97\include;%(AdditionalIncludeDirectories) + .;..\..\lame-3.98.4;..\..\lame-3.98.4\include;%(AdditionalIncludeDirectories) NDEBUG;_WINDOWS;WIN32;HAVE_CONFIG_H;%(PreprocessorDefinitions) true MultiThreaded @@ -90,7 +90,7 @@ /GAy /QIfdiv /QI0f %(AdditionalOptions) MaxSpeed - .;..\..\lame-3.97;..\..\lame-3.97\include;%(AdditionalIncludeDirectories) + .;..\..\lame-3.98.4;..\..\lame-3.98.4\include;%(AdditionalIncludeDirectories) NDEBUG;_WINDOWS;WIN32;HAVE_CONFIG_H;%(PreprocessorDefinitions) true MultiThreaded @@ -109,7 +109,7 @@ Disabled - .;..\..\lame-3.97;..\..\lame-3.97\include;%(AdditionalIncludeDirectories) + .;..\..\lame-3.98.4;..\..\lame-3.98.4\include;%(AdditionalIncludeDirectories) _DEBUG;_WINDOWS;WIN32;HAVE_CONFIG_H;%(PreprocessorDefinitions) MultiThreadedDebug TurnOffAllWarnings @@ -129,7 +129,7 @@ Disabled - .;..\..\lame-3.97;..\..\lame-3.97\include;%(AdditionalIncludeDirectories) + .;..\..\lame-3.98.4;..\..\lame-3.98.4\include;%(AdditionalIncludeDirectories) _DEBUG;_WINDOWS;WIN32;HAVE_CONFIG_H;%(PreprocessorDefinitions) MultiThreadedDebug TurnOffAllWarnings @@ -144,7 +144,7 @@ - + Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -158,7 +158,7 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - + Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -172,7 +172,7 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - + Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -186,7 +186,7 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - + Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -200,7 +200,7 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - + Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -214,7 +214,7 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - + Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -228,7 +228,7 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - + Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -242,7 +242,7 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - + Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -256,7 +256,7 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - + Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -270,7 +270,7 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - + Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -284,7 +284,7 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - + Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -298,7 +298,7 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - + Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -312,7 +312,7 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - + Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -326,7 +326,7 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - + Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -340,7 +340,7 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - + Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -358,7 +358,7 @@ %(PreprocessorDefinitions) Level1 - + Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -372,7 +372,7 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - + Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -386,7 +386,7 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - + Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -400,7 +400,7 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - + Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -414,7 +414,7 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) - + Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) @@ -430,37 +430,37 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + diff --git a/libs/win32/libmp3lame/libmp3lame_vc7.vcproj b/libs/win32/libmp3lame/libmp3lame_vc7.vcproj index 5f4e5c3255..f384796889 100644 --- a/libs/win32/libmp3lame/libmp3lame_vc7.vcproj +++ b/libs/win32/libmp3lame/libmp3lame_vc7.vcproj @@ -45,7 +45,7 @@ Name="VCCLCompilerTool" AdditionalOptions="/GAy /QIfdiv /QI0f" Optimization="2" - AdditionalIncludeDirectories=".;"..\..\lame-3.97";"..\..\lame-3.97\include"" + AdditionalIncludeDirectories=".;"..\..\lame-3.98.4";"..\..\lame-3.98.4\include"" PreprocessorDefinitions="NDEBUG;_WINDOWS;WIN32;HAVE_CONFIG_H" StringPooling="true" RuntimeLibrary="0" @@ -117,7 +117,7 @@ Name="VCCLCompilerTool" AdditionalOptions="/GAy /QIfdiv /QI0f" Optimization="2" - AdditionalIncludeDirectories=".;"..\..\lame-3.97";"..\..\lame-3.97\include"" + AdditionalIncludeDirectories=".;"..\..\lame-3.98.4";"..\..\lame-3.98.4\include"" PreprocessorDefinitions="NDEBUG;_WINDOWS;WIN32;HAVE_CONFIG_H" StringPooling="true" RuntimeLibrary="0" @@ -184,7 +184,7 @@ @@ -1281,35 +1281,35 @@ Filter=".nas" > diff --git a/scripts/perl/tonegen/rtttl2tgml.pl b/scripts/perl/tonegen/rtttl2tgml.pl index 820e36cc4e..39d4ab715a 100644 --- a/scripts/perl/tonegen/rtttl2tgml.pl +++ b/scripts/perl/tonegen/rtttl2tgml.pl @@ -18,8 +18,19 @@ our $NOTES = { my $file = shift or die "no file\n"; +my $rtttl; +my $cr = "\n"; -my $rtttl = `cat $file`; +if ($file eq "-nocr") { + $cr = ""; + $file = shift; +} + +if ($file eq "-") { + $rtttl = ; +} else { + $rtttl = `cat $file`; +} $rtttl =~ s/\n//g; @@ -45,16 +56,11 @@ if ($r->has_errors()) { $all = $r->get_notes(); -$ms_per_beat = int (60000 / $r->get_bpm()); +$ms_per_beat = int (6000 / $r->get_bpm()); foreach (@{$all}) { - - my $ms = $ms_per_beat * (1 / $_->[0]) * 4; - - #print STDERR "$_->[0] $_->[1] $_->[2] $_->[3]\n"; - - print "%($ms, 0, $NOTES->{$_->[1]}->[$_->[2]]);\n"; - + my $ms = ($ms_per_beat * $_->[2]); + print "%($ms,0,$NOTES->{$_->[1]}->[$_->[2]]);" . $cr; } diff --git a/scripts/trace/sipgrep b/scripts/trace/sipgrep index 7bd5daed4d..474a2d5c7b 100755 --- a/scripts/trace/sipgrep +++ b/scripts/trace/sipgrep @@ -287,7 +287,7 @@ sub print_out { open(DBG, ">>$filedebug"); $lcolor = 'reset' if(!(defined $debugfilecolors)); - print DBG color $lcolor; + print DBG color $lcolor if(!(defined $debugfilecolors)); print DBG $ltext; close(DBG); } diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index 31da5a9bf1..8d2a8122b9 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -253,8 +253,6 @@ struct switch_runtime { int multiple_registrations; uint32_t max_db_handles; uint32_t db_handle_timeout; - int curl_count; - int ssl_count; int cpu_count; }; diff --git a/src/include/switch.h b/src/include/switch.h index de099f1b94..98a46890e6 100644 --- a/src/include/switch.h +++ b/src/include/switch.h @@ -109,6 +109,7 @@ #include "switch_platform.h" #include "switch_types.h" #include "switch_apr.h" +#include "switch_curl.h" #include "switch_mprintf.h" #include "switch_core_db.h" #include "switch_dso.h" diff --git a/src/include/switch_caller.h b/src/include/switch_caller.h index fde3372105..09ff57beb6 100644 --- a/src/include/switch_caller.h +++ b/src/include/switch_caller.h @@ -120,6 +120,9 @@ typedef struct profile_node_s { struct switch_caller_profile *next; switch_call_direction_t direction; profile_node_t *soft; + char *uuid_str; + char *clone_of; + char *transfer_source; }; /*! \brief An Abstract Representation of a dialplan Application */ diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index d388777c33..94eb9e571d 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -88,8 +88,8 @@ SWITCH_DECLARE(int) switch_channel_test_ready(switch_channel_t *channel, switch_ #define switch_channel_up(_channel) (switch_channel_check_signal(_channel, SWITCH_TRUE) || switch_channel_get_state(_channel) < CS_HANGUP) #define switch_channel_down(_channel) (switch_channel_check_signal(_channel, SWITCH_TRUE) || switch_channel_get_state(_channel) >= CS_HANGUP) -#define switch_channel_up_nosig(_channel) switch_channel_get_state(_channel) < CS_HANGUP -#define switch_channel_down_nosig(_channel) switch_channel_get_state(_channel) >= CS_HANGUP +#define switch_channel_up_nosig(_channel) (switch_channel_get_state(_channel) < CS_HANGUP) +#define switch_channel_down_nosig(_channel) (switch_channel_get_state(_channel) >= CS_HANGUP) #define switch_channel_media_ack(_channel) (!switch_channel_test_cap(_channel, CC_MEDIA_ACK) || switch_channel_test_flag(_channel, CF_MEDIA_ACK)) @@ -271,6 +271,8 @@ SWITCH_DECLARE(const char *) switch_channel_get_variable_partner(switch_channel_ SWITCH_DECLARE(const char *) switch_channel_get_hold_music(switch_channel_t *channel); SWITCH_DECLARE(const char *) switch_channel_get_hold_music_partner(switch_channel_t *channel); +SWITCH_DECLARE(uint32_t) switch_channel_del_variable_prefix(switch_channel_t *channel, const char *prefix); + #define switch_channel_set_variable(_channel, _var, _val) switch_channel_set_variable_var_check(_channel, _var, _val, SWITCH_TRUE) #define switch_channel_set_variable_partner(_channel, _var, _val) switch_channel_set_variable_partner_var_check(_channel, _var, _val, SWITCH_TRUE) @@ -387,6 +389,7 @@ SWITCH_DECLARE(uint32_t) switch_channel_test_flag_partner(switch_channel_t *chan \param flag flag to set */ SWITCH_DECLARE(void) switch_channel_set_state_flag(switch_channel_t *channel, switch_channel_flag_t flag); +SWITCH_DECLARE(void) switch_channel_clear_state_flag(switch_channel_t *channel, switch_channel_flag_t flag); /*! \brief Clear given flag(s) from a channel diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 7f1db105f8..9d0893565f 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -25,7 +25,7 @@ * * Anthony Minessale II * Luke Dashjr (OpenMethods, LLC) - * + * Joseph Sullivan * * switch_core.h -- Core Library * @@ -436,9 +436,6 @@ SWITCH_DECLARE(void) switch_core_session_rwunlock(_In_ switch_core_session_t *se */ SWITCH_DECLARE(int) switch_core_add_state_handler(_In_ const switch_state_handler_table_t *state_handler); -SWITCH_DECLARE(int) switch_core_curl_count(int *val); -SWITCH_DECLARE(int) switch_core_ssl_count(int *val); - /*! \brief Remove a global state handler \param state_handler the state handler to remove @@ -467,6 +464,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_new_memory_pool(_Out_ switch */ #define switch_core_new_memory_pool(p) switch_core_perform_new_memory_pool(p, __FILE__, __SWITCH_FUNC__, __LINE__) +SWITCH_DECLARE(int) switch_core_session_sync_clock(void); SWITCH_DECLARE(switch_status_t) switch_core_perform_destroy_memory_pool(_Inout_ switch_memory_pool_t **pool, _In_z_ const char *file, _In_z_ const char *func, _In_ int line); /*! @@ -1307,11 +1305,11 @@ SWITCH_DECLARE(void *) switch_core_hash_find_rdlock(_In_ switch_hash_t *hash, _I /*! \brief Gets the first element of a hashtable - \param depricate_me [deprecated] NULL + \param deprecate_me [deprecated] NULL \param hash the hashtable to use \return The element, or NULL if it wasn't found */ -SWITCH_DECLARE(switch_hash_index_t *) switch_hash_first(char *depricate_me, _In_ switch_hash_t *hash); +SWITCH_DECLARE(switch_hash_index_t *) switch_hash_first(char *deprecate_me, _In_ switch_hash_t *hash); /*! \brief Gets the next element of a hashtable @@ -1957,6 +1955,18 @@ SWITCH_DECLARE(FILE *) switch_core_data_channel(switch_text_channel_t channel); */ SWITCH_DECLARE(switch_bool_t) switch_core_ready(void); +/*! + \brief Determines if the core is ready to take inbound calls + \return SWITCH_TRUE or SWITCH_FALSE +*/ +SWITCH_DECLARE(switch_bool_t) switch_core_ready_inbound(void); + +/*! + \brief Determines if the core is ready to place outbound calls + \return SWITCH_TRUE or SWITCH_FALSE +*/ +SWITCH_DECLARE(switch_bool_t) switch_core_ready_outbound(void); + /*! \brief return core flags \return core flags diff --git a/src/include/switch_cpp.h b/src/include/switch_cpp.h index 70e484bf51..44e85185a6 100644 --- a/src/include/switch_cpp.h +++ b/src/include/switch_cpp.h @@ -65,6 +65,10 @@ Note that the first parameter to the new operator is implicitly handled by c++.. */ + +SWITCH_DECLARE(void) setGlobalVariable(char *var_name, char *var_val); +SWITCH_DECLARE(char *) getGlobalVariable(char *var_name); + SWITCH_DECLARE(void) consoleLog(char *level_str, char *msg); SWITCH_DECLARE(void) consoleCleanLog(char *msg); @@ -185,7 +189,7 @@ SWITCH_DECLARE(bool) email(char *to, char *from, char *headers = NULL, char *bod SWITCH_DECLARE_CONSTRUCTOR EventConsumer(const char *event_name = NULL, const char *subclass_name = ""); SWITCH_DECLARE_CONSTRUCTOR ~ EventConsumer(); SWITCH_DECLARE(int) bind(const char *event_name, const char *subclass_name = ""); - SWITCH_DECLARE(Event *) pop(int block = 0); + SWITCH_DECLARE(Event *) pop(int block = 0, int timeout = 0); }; #ifdef SWIG diff --git a/src/include/switch_curl.h b/src/include/switch_curl.h index 4d44595e0d..17c4bd6ce1 100644 --- a/src/include/switch_curl.h +++ b/src/include/switch_curl.h @@ -30,34 +30,27 @@ #ifndef __SWITCH_CURL_H #define __SWITCH_CURL_H +#include "curl/curl.h" -#include -#include -static inline void switch_curl_init(void) -{ - int curl_count = switch_core_curl_count(NULL); +typedef void switch_CURL; +typedef struct curl_slist switch_curl_slist_t; +typedef int switch_CURLINFO; +typedef int switch_CURLcode; +typedef int switch_CURLoption; - if (curl_count == 0) { - curl_global_init(CURL_GLOBAL_ALL); - } - - curl_count++; - switch_core_curl_count(&curl_count); -} - -static inline void switch_curl_destroy() -{ - int curl_count = switch_core_curl_count(NULL); - - curl_count--; - - if (curl_count == 0) { - curl_global_cleanup(); - } - switch_core_curl_count(&curl_count); -} +SWITCH_DECLARE(switch_CURL *) switch_curl_easy_init(void); +SWITCH_DECLARE(switch_CURLcode) switch_curl_easy_perform(switch_CURL *handle); +SWITCH_DECLARE(switch_CURLcode) switch_curl_easy_getinfo(switch_CURL *curl, switch_CURLINFO info, ... ); +SWITCH_DECLARE(void) switch_curl_easy_cleanup(switch_CURL *handle); +SWITCH_DECLARE(switch_curl_slist_t *) switch_curl_slist_append(switch_curl_slist_t * list, const char * string ); +SWITCH_DECLARE(void) switch_curl_slist_free_all(switch_curl_slist_t * list); +SWITCH_DECLARE(switch_CURLcode) switch_curl_easy_setopt(CURL *handle, switch_CURLoption option, ...); +SWITCH_DECLARE(const char *) switch_curl_easy_strerror(switch_CURLcode errornum ); +SWITCH_DECLARE(void) switch_curl_init(void); +SWITCH_DECLARE(void) switch_curl_destroy(void); + #endif diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h index 901519f7dd..6f883a933c 100644 --- a/src/include/switch_ivr.h +++ b/src/include/switch_ivr.h @@ -155,6 +155,21 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_count(switch_core_sess const char *terminators, char *terminator, uint32_t first_timeout, uint32_t digit_timeout, uint32_t abs_timeout); +/*! + \brief play a file to the session while doing speech recognition. + \param session the session to play and detect on + \param file the path to the file + \param mod_name the module name of the ASR library + \param grammar the grammar text, URI, or local file name + \param result of speech recognition, allocated from the session pool + \return SWITCH_STATUS_SUCCESS if all is well +*/ +SWITCH_DECLARE(switch_status_t) switch_ivr_play_and_detect_speech(switch_core_session_t *session, + const char *file, + const char *mod_name, + const char *grammar, + char **result); + /*! \brief Engage background Speech detection on a session \param session the session to attach @@ -896,6 +911,7 @@ SWITCH_DECLARE(switch_bool_t) switch_ivr_uuid_exists(const char *uuid); +SWITCH_DECLARE(const char *) switch_ivr_dmachine_get_name(switch_ivr_dmachine_t *dmachine); SWITCH_DECLARE(void) switch_ivr_dmachine_set_match_callback(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_callback_t match_callback); SWITCH_DECLARE(void) switch_ivr_dmachine_set_nonmatch_callback(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_callback_t nonmatch_callback); SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_create(switch_ivr_dmachine_t **dmachine_p, @@ -932,6 +948,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_process_fh(switch_core_session_t *ses SWITCH_DECLARE(switch_status_t) switch_ivr_insert_file(switch_core_session_t *session, const char *file, const char *insert_file, switch_size_t sample_point); SWITCH_DECLARE(switch_status_t) switch_ivr_create_message_reply(switch_event_t **reply, switch_event_t *message, const char *new_proto); +SWITCH_DECLARE(char *) switch_ivr_check_presence_mapping(const char *exten_name, const char *domain_name); +SWITCH_DECLARE(switch_status_t) switch_ivr_kill_uuid(const char *uuid, switch_call_cause_t cause); /** @} */ diff --git a/src/include/switch_rtcp_frame.h b/src/include/switch_rtcp_frame.h index 1c718a089f..5d06294304 100644 --- a/src/include/switch_rtcp_frame.h +++ b/src/include/switch_rtcp_frame.h @@ -38,7 +38,20 @@ #include +#define MAX_REPORT_BLOCKS 5 + SWITCH_BEGIN_EXTERN_C + +struct switch_rtcp_report_block_frame { + uint32_t ssrc; /* The SSRC identifier of the source to which the information in this reception report block pertains. */ + uint8_t fraction; /* The fraction of RTP data packets from source SSRC_n lost since the previous SR or RR packet was sent */ + uint32_t lost; /* The total number of RTP data packets from source SSRC_n that have been lost since the beginning of reception */ + uint32_t highest_sequence_number_received; + uint32_t jitter; /* An estimate of the statistical variance of the RTP data packet interarrival time, measured in timestamp units and expressed as an unsigned integer. */ + uint32_t lsr; /* The middle 32 bits out of 64 in the NTP timestamp */ + uint32_t dlsr; /* The delay, expressed in units of 1/65536 seconds, between receiving the last SR packet from source SSRC_n and sending this reception report block */ +}; + /*! \brief An abstraction of a rtcp frame */ struct switch_rtcp_frame { @@ -58,6 +71,10 @@ SWITCH_BEGIN_EXTERN_C uint32_t octect_count; + uint32_t nb_reports; + + struct switch_rtcp_report_block_frame reports[MAX_REPORT_BLOCKS]; + }; SWITCH_END_EXTERN_C diff --git a/src/include/switch_ssl.h b/src/include/switch_ssl.h index 30b3b07ec5..24f660b459 100644 --- a/src/include/switch_ssl.h +++ b/src/include/switch_ssl.h @@ -36,7 +36,7 @@ static switch_mutex_t **ssl_mutexes; static switch_memory_pool_t *ssl_pool = NULL; - +static int ssl_count = 0; static inline void switch_ssl_ssl_lock_callback(int mode, int type, char *file, int line) { @@ -56,7 +56,6 @@ static inline unsigned long switch_ssl_ssl_thread_id(void) static inline void switch_ssl_init_ssl_locks(void) { - int ssl_count = switch_core_ssl_count(NULL); int i, num; if (ssl_count == 0) { @@ -77,17 +76,13 @@ static inline void switch_ssl_init_ssl_locks(void) } ssl_count++; - switch_core_ssl_count(&ssl_count); } static inline void switch_ssl_destroy_ssl_locks() { int i; - int ssl_count = switch_core_ssl_count(NULL); - ssl_count--; - - if (ssl_count == 0) { + if (ssl_count == 1) { CRYPTO_set_locking_callback(NULL); for (i = 0; i < CRYPTO_num_locks(); i++) { if (ssl_mutexes[i]) { @@ -96,10 +91,8 @@ static inline void switch_ssl_destroy_ssl_locks() } OPENSSL_free(ssl_mutexes); + ssl_count--; } - - switch_core_ssl_count(&ssl_count); - } #else static inline void switch_ssl_init_ssl_locks(void) { return; } diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 21dfa51339..ea65319924 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -25,6 +25,7 @@ * * Anthony Minessale II * Bret McDanel + * Joseph Sullivan * * switch_types.h -- Data Types * @@ -131,6 +132,8 @@ SWITCH_BEGIN_EXTERN_C #define SWITCH_COPY_XML_CDR_VARIABLE "copy_xml_cdr" #define SWITCH_CURRENT_APPLICATION_VARIABLE "current_application" #define SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE "proto_specific_hangup_cause" +#define SWITCH_TRANSFER_HISTORY_VARIABLE "transfer_history" +#define SWITCH_TRANSFER_SOURCE_VARIABLE "transfer_source" #define SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE "execute_on_answer" #define SWITCH_CHANNEL_EXECUTE_ON_PRE_ANSWER_VARIABLE "execute_on_pre_answer" @@ -291,23 +294,27 @@ typedef uint32_t switch_eavesdrop_flag_t; typedef enum { SCF_NONE = 0, SCF_USE_SQL = (1 << 0), - SCF_NO_NEW_SESSIONS = (1 << 1), - SCF_SHUTTING_DOWN = (1 << 2), - SCF_VG = (1 << 3), - SCF_RESTART = (1 << 4), - SCF_SHUTDOWN_REQUESTED = (1 << 5), - SCF_USE_AUTO_NAT = (1 << 6), - SCF_EARLY_HANGUP = (1 << 7), - SCF_CALIBRATE_CLOCK = (1 << 8), - SCF_USE_HEAVY_TIMING = (1 << 9), - SCF_USE_CLOCK_RT = (1 << 10), - SCF_VERBOSE_EVENTS = (1 << 11), - SCF_USE_WIN32_MONOTONIC = (1 << 12), - SCF_AUTO_SCHEMAS = (1 << 13), - SCF_MINIMAL = (1 << 14), - SCF_USE_NAT_MAPPING = (1 << 15), - SCF_CLEAR_SQL = (1 << 16), - SCF_THREADED_SYSTEM_EXEC = (1 << 17) + SCF_NO_NEW_OUTBOUND_SESSIONS = (1 << 1), + SCF_NO_NEW_INBOUND_SESSIONS = (1 << 2), + SCF_NO_NEW_SESSIONS = (SCF_NO_NEW_OUTBOUND_SESSIONS | SCF_NO_NEW_INBOUND_SESSIONS), + SCF_SHUTTING_DOWN = (1 << 3), + SCF_VG = (1 << 4), + SCF_RESTART = (1 << 5), + SCF_SHUTDOWN_REQUESTED = (1 << 6), + SCF_USE_AUTO_NAT = (1 << 7), + SCF_EARLY_HANGUP = (1 << 8), + SCF_CALIBRATE_CLOCK = (1 << 9), + SCF_USE_HEAVY_TIMING = (1 << 10), + SCF_USE_CLOCK_RT = (1 << 11), + SCF_VERBOSE_EVENTS = (1 << 12), + SCF_USE_WIN32_MONOTONIC = (1 << 13), + SCF_AUTO_SCHEMAS = (1 << 14), + SCF_MINIMAL = (1 << 15), + SCF_USE_NAT_MAPPING = (1 << 16), + SCF_CLEAR_SQL = (1 << 17), + SCF_THREADED_SYSTEM_EXEC = (1 << 18), + SCF_SYNC_CLOCK_REQUESTED = (1 << 19), + SCF_CORE_ODBC_REQ = (1 << 20) } switch_core_flag_enum_t; typedef uint32_t switch_core_flag_t; @@ -347,7 +354,8 @@ typedef enum { SSM_NA, SSM_PRONOUNCED, SSM_ITERATED, - SSM_COUNTED + SSM_COUNTED, + SSM_PRONOUNCED_YEAR } switch_say_method_t; /* WARNING, Do not forget to update *SAY_TYPE_NAMES[] in src/switch_ivr_say.c */ @@ -685,7 +693,7 @@ typedef enum { */ - RTP_BUG_ACCEPT_ANY_PACKETS = (1 << 7) + RTP_BUG_ACCEPT_ANY_PACKETS = (1 << 7), /* Oracle's Contact Center Anywhere (CCA) likes to use a single RTP socket to send all its outbound audio. @@ -694,6 +702,21 @@ typedef enum { */ + RTP_BUG_GEN_ONE_GEN_ALL = (1 << 8) + + /* + Some RTP endpoints (and by some we mean *cough* _SONUS_!) do not like it when the timestamps jump forward or backwards in time. + So say you are generating a file that says "please wait for me to complete your call, or generating ringback" + Now you place and outbound call and you are bridging. Well, while you were playing the file, you were generating your own RTP timestamps. + But, now that you have a remote RTP stream, you'd rather send those timestamps as-is in case they will be fed to a remote jitter buffer...... + Ok, so this causes the audio to completely fade out despite the fact that we send the mark bit which should give them heads up its happening. + + Sigh, This flag will tell FreeSWITCH that if it ever generates even one RTP packet itself, to continue to generate all of them and ignore the + actual timestamps in the frames. + + */ + + } switch_rtp_bug_flag_t; #ifdef _MSC_VER @@ -852,6 +875,8 @@ typedef enum { SWITCH_MESSAGE_INDICATE_JITTER_BUFFER, SWITCH_MESSAGE_INDICATE_RECOVERY_REFRESH, SWITCH_MESSAGE_INDICATE_SIGNAL_DATA, + SWITCH_MESSAGE_INDICATE_INFO, + SWITCH_MESSAGE_INDICATE_AUDIO_DATA, SWITCH_MESSAGE_INVALID } switch_core_session_message_types_t; @@ -1163,6 +1188,7 @@ typedef enum { CF_BRIDGE_NOWRITE, CF_RECOVERED, CF_JITTERBUFFER, + CF_JITTERBUFFER_PLC, CF_DIALPLAN, CF_BLOCK_BROADCAST_UNTIL_MEDIA, CF_CNG_PLC, @@ -1171,6 +1197,8 @@ typedef enum { CF_SIGNAL_DATA, CF_SIMPLIFY, CF_ZOMBIE_EXEC, + CF_INTERCEPT, + CF_INTERCEPTED, /* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */ /* IF YOU ADD NEW ONES CHECK IF THEY SHOULD PERSIST OR ZERO THEM IN switch_core_session.c switch_core_session_request_xml() */ CF_FLAG_MAX @@ -1374,6 +1402,9 @@ SMBF_READ_REPLACE - Replace the Read Stream SMBF_STEREO - Record in stereo SMBF_ANSWER_RECORD_REQ - Don't record until the channel is answered SMBF_THREAD_LOCK - Only let the same thread who created the bug remove it. +SMBF_PRUNE - +SMBF_NO_PAUSE - +SMBF_STEREO_SWAP - Record in stereo: Write Stream - left channel, Read Stream - right channel */ typedef enum { @@ -1387,7 +1418,8 @@ typedef enum { SMBF_ANSWER_REQ = (1 << 6), SMBF_THREAD_LOCK = (1 << 7), SMBF_PRUNE = (1 << 8), - SMBF_NO_PAUSE = (1 << 9) + SMBF_NO_PAUSE = (1 << 9), + SMBF_STEREO_SWAP = (1 << 10) } switch_media_bug_flag_enum_t; typedef uint32_t switch_media_bug_flag_t; @@ -1659,11 +1691,17 @@ typedef enum { SWITCH_CAUSE_MEDIA_TIMEOUT = 604, SWITCH_CAUSE_PICKED_OFF = 605, SWITCH_CAUSE_USER_NOT_REGISTERED = 606, - SWITCH_CAUSE_PROGRESS_TIMEOUT = 607 + SWITCH_CAUSE_PROGRESS_TIMEOUT = 607, + SWITCH_CAUSE_INVALID_GATEWAY = 608, + SWITCH_CAUSE_GATEWAY_DOWN = 609, + SWITCH_CAUSE_INVALID_URL = 610, + SWITCH_CAUSE_INVALID_PROFILE = 611 } switch_call_cause_t; typedef enum { SCSC_PAUSE_INBOUND, + SCSC_PAUSE_OUTBOUND, + SCSC_PAUSE_ALL, SCSC_HUPALL, SCSC_SHUTDOWN, SCSC_CHECK_RUNNING, @@ -1689,9 +1727,12 @@ typedef enum { SCSC_MIN_IDLE_CPU, SCSC_VERBOSE_EVENTS, SCSC_SHUTDOWN_CHECK, + SCSC_PAUSE_INBOUND_CHECK, + SCSC_PAUSE_OUTBOUND_CHECK, SCSC_PAUSE_CHECK, SCSC_READY_CHECK, - SCSC_THREADED_SYSTEM_EXEC + SCSC_THREADED_SYSTEM_EXEC, + SCSC_SYNC_CLOCK_WHEN_IDLE } switch_session_ctl_t; typedef enum { diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h index 33b4173513..343a2ce62e 100644 --- a/src/include/switch_utils.h +++ b/src/include/switch_utils.h @@ -240,6 +240,7 @@ SWITCH_DECLARE(switch_status_t) switch_frame_alloc(switch_frame_t **frame, switc SWITCH_DECLARE(switch_status_t) switch_frame_dup(switch_frame_t *orig, switch_frame_t **clone); SWITCH_DECLARE(switch_status_t) switch_frame_free(switch_frame_t **frame); SWITCH_DECLARE(switch_bool_t) switch_is_number(const char *str); +SWITCH_DECLARE(char *) switch_find_parameter(const char *str, const char *param, switch_memory_pool_t *pool); /*! \brief Evaluate the truthfullness of a string expression @@ -830,6 +831,9 @@ SWITCH_DECLARE(int) switch_split_user_domain(char *in, char **user, char **domai SWITCH_DECLARE(const char *) switch_inet_ntop(int af, void const *src, char *dst, size_t size); #endif +SWITCH_DECLARE(char *) switch_uuid_str(char *buf, switch_size_t len); +SWITCH_DECLARE(char *) switch_format_number(const char *num); + SWITCH_END_EXTERN_C #endif /* For Emacs: diff --git a/src/include/switch_xml.h b/src/include/switch_xml.h index 6961b2da23..0d436fac2f 100644 --- a/src/include/switch_xml.h +++ b/src/include/switch_xml.h @@ -421,7 +421,7 @@ SWITCH_DECLARE(switch_status_t) switch_xml_unbind_search_function_ptr(_In_ switc ///\return the section mask SWITCH_DECLARE(switch_xml_section_t) switch_xml_parse_section_string(_In_opt_z_ const char *str); -SWITCH_DECLARE(int) switch_xml_std_datetime_check(switch_xml_t xcond); +SWITCH_DECLARE(int) switch_xml_std_datetime_check(switch_xml_t xcond, int *offset); SWITCH_DECLARE(switch_status_t) switch_xml_locate_language(switch_xml_t *root, switch_xml_t *node, switch_event_t *params, switch_xml_t *language, switch_xml_t *phrases, switch_xml_t *macros, const char *str_language); diff --git a/src/mod/applications/mod_blacklist/mod_blacklist.2010.vcxproj b/src/mod/applications/mod_blacklist/mod_blacklist.2010.vcxproj new file mode 100644 index 0000000000..6f50db85fc --- /dev/null +++ b/src/mod/applications/mod_blacklist/mod_blacklist.2010.vcxproj @@ -0,0 +1,131 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + mod_blacklist + {50AAC2CE-BFC9-4912-87CC-C6381850D735} + mod_blacklist + Win32Proj + + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + + + + + + + + false + + + + + + + X64 + + + + + + + false + + + MachineX64 + + + + + + + + + false + + + + + + + X64 + + + + + + + false + + + MachineX64 + + + + + + + + {202d7a4e-760d-4d0e-afa1-d7459ced30ff} + false + + + + + + diff --git a/src/mod/applications/mod_blacklist/mod_blacklist.c b/src/mod/applications/mod_blacklist/mod_blacklist.c index bb2cd7828e..39db253396 100644 --- a/src/mod/applications/mod_blacklist/mod_blacklist.c +++ b/src/mod/applications/mod_blacklist/mod_blacklist.c @@ -166,6 +166,7 @@ static switch_status_t do_config(switch_bool_t reload) "blacklist check \n" \ "blacklist add \n" \ "blacklist del \n" \ + "blacklist save \n" \ "blacklist reload\n" \ "blacklist help\n" @@ -249,7 +250,7 @@ SWITCH_STANDARD_API(blacklist_api_function) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Removed [%s] from list [%s]\n", argv[2], argv[1]); switch_mutex_unlock(bl->list_mutex); stream->write_function(stream, "+OK\n"); - } else if (!strcasecmp(argv[0], "dump")) { + } else if (!strcasecmp(argv[0], "save")) { switch_hash_index_t *hi; void *val; const void *var; @@ -276,15 +277,19 @@ SWITCH_STANDARD_API(blacklist_api_function) goto done; } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Dumping %s to %s\n", argv[1], filename); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Saving %s to %s\n", argv[1], filename); switch_mutex_lock(globals.lists_mutex); - if (switch_file_open(&fd, filename, SWITCH_FOPEN_WRITE, SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE, globals.pool) == SWITCH_STATUS_SUCCESS) { + if (switch_file_open(&fd, filename, SWITCH_FOPEN_WRITE | SWITCH_FOPEN_TRUNCATE | SWITCH_FOPEN_CREATE, SWITCH_FPROT_OS_DEFAULT, globals.pool) + == SWITCH_STATUS_SUCCESS) { for (hi = switch_hash_first(NULL, bl->list); hi; hi = switch_hash_next(hi)) { switch_hash_this(hi, &var, NULL, &val); switch_file_printf(fd, "%s\n", (char *)var); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "adding %s to the dump file\n", (char *)var); } stream->write_function(stream, "+OK\n"); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "couldn't open %s for writing\n", filename); } switch_mutex_unlock(globals.lists_mutex); } else if (!strcasecmp(argv[0], "reload")) { diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c index aa95b1e28c..b8353fae8c 100644 --- a/src/mod/applications/mod_callcenter/mod_callcenter.c +++ b/src/mod/applications/mod_callcenter/mod_callcenter.c @@ -1433,6 +1433,8 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_agent", "%s", h->agent_name); switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_agent_type", "%s", h->agent_type); switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_side", "%s", "agent"); + switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "loopback_bowout", "false"); + switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "loopback_bowout_on_execute", "false"); switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "ignore_early_media", "true"); t_agent_called = local_epoch_time_now(NULL); @@ -1496,8 +1498,12 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa if ((other_loopback_session = switch_core_session_locate(other_loopback_leg_uuid))) { switch_channel_t *other_loopback_channel = switch_core_session_get_channel(other_loopback_session); - const char *real_uuid = switch_channel_get_variable(other_loopback_channel, SWITCH_SIGNAL_BOND_VARIABLE); + const char *real_uuid = NULL; + /* Wait for the real channel to be fully bridged */ + switch_channel_wait_for_flag(other_loopback_channel, CF_BRIDGED, SWITCH_TRUE, 5000, member_channel); + + real_uuid = switch_channel_get_variable(other_loopback_channel, SWITCH_SIGNAL_BOND_VARIABLE); switch_channel_set_variable(other_loopback_channel, "cc_member_pre_answer_uuid", NULL); /* Switch the agent session */ @@ -1507,9 +1513,6 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa agent_uuid = switch_core_session_get_uuid(agent_session); agent_channel = switch_core_session_get_channel(agent_session); - /* Wait for the real channel to be fully bridged */ - switch_channel_wait_for_flag(agent_channel, CF_BRIDGED, SWITCH_TRUE, 5000, member_channel); - if (!switch_channel_test_flag(agent_channel, CF_BRIDGED)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Timeout waiting for real channel to be bridged (agent '%s')\n", h->agent_name); } else { @@ -2281,9 +2284,20 @@ void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj } /* Will drop the caller if no agent was found for more than X seconds */ - if (queue->max_wait_time_with_no_agent > 0 && m->t_member_called < queue->last_agent_exist_check - queue->max_wait_time_with_no_agent_time_reached && - queue->last_agent_exist_check - queue->last_agent_exist >= queue->max_wait_time_with_no_agent) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Member %s <%s> in queue '%s' reached max wait with no agent time\n", m->member_cid_name, m->member_cid_number, m->queue_name); + if (queue->max_wait_time_with_no_agent > 0 && + (queue->last_agent_exist >= m->t_member_called || queue->max_wait_time_with_no_agent_time_reached == 0) && + queue->last_agent_exist_check - queue->last_agent_exist > queue->max_wait_time_with_no_agent) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Member %s <%s> in queue '%s' reached max wait of %d sec. with no agent\n", m->member_cid_name, m->member_cid_number, m->queue_name, queue->max_wait_time_with_no_agent); + m->member_cancel_reason = CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT; + switch_channel_set_flag_value(member_channel, CF_BREAK, 2); + } + + /* Will drop the NEW caller if no agent was found for more than X seconds once they join */ + if (queue->max_wait_time_with_no_agent_time_reached > 0 && + queue->last_agent_exist < m->t_member_called && + queue->last_agent_exist_check - queue->last_agent_exist > queue->max_wait_time_with_no_agent && + queue->last_agent_exist_check - m->t_member_called >= queue->max_wait_time_with_no_agent_time_reached) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Member %s <%s> in queue '%s' reached max wait of %d sec. with no agent plus join grace period of %d sec.\n", m->member_cid_name, m->member_cid_number, m->queue_name, queue->max_wait_time_with_no_agent, queue->max_wait_time_with_no_agent_time_reached); m->member_cancel_reason = CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT; switch_channel_set_flag_value(member_channel, CF_BREAK, 2); } diff --git a/src/mod/applications/mod_cidlookup/Makefile b/src/mod/applications/mod_cidlookup/Makefile index 5ffe1d8476..24790d0d39 100644 --- a/src/mod/applications/mod_cidlookup/Makefile +++ b/src/mod/applications/mod_cidlookup/Makefile @@ -1,4 +1,3 @@ -WANT_CURL=yes BASE=../../../.. include $(BASE)/build/modmake.rules diff --git a/src/mod/applications/mod_cidlookup/mod_cidlookup.c b/src/mod/applications/mod_cidlookup/mod_cidlookup.c index ba69f6fb6b..fc32e6fe21 100755 --- a/src/mod/applications/mod_cidlookup/mod_cidlookup.c +++ b/src/mod/applications/mod_cidlookup/mod_cidlookup.c @@ -30,7 +30,7 @@ */ #include -#include +#include #define SWITCH_REWIND_STREAM(s) s.end = s.data @@ -360,7 +360,7 @@ static size_t file_callback(void *ptr, size_t size, size_t nmemb, void *data) } static long do_lookup_url(switch_memory_pool_t *pool, switch_event_t *event, char **response, const char *query, struct curl_httppost *post, - struct curl_slist *headers, int timeout) + switch_curl_slist_t *headers, int timeout) { switch_time_t start_time = switch_micro_time_now(); switch_time_t time_diff = 0; @@ -375,49 +375,49 @@ static long do_lookup_url(switch_memory_pool_t *pool, switch_event_t *event, cha SWITCH_STANDARD_STREAM(http_data.stream); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "url: %s\n", query); - curl_handle = curl_easy_init(); + curl_handle = switch_curl_easy_init(); - curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 0); - curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1); + switch_curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 0); + switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1); if (!strncasecmp(query, "https", 5)) { - curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0); - curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0); + switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0); + switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0); } if (post) { - curl_easy_setopt(curl_handle, CURLOPT_HTTPPOST, post); + switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPPOST, post); } else { - curl_easy_setopt(curl_handle, CURLOPT_HTTPGET, 1); + switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPGET, 1); } if (headers) { - curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers); + switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers); } - curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); - curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10); + switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); + switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10); /* TIMEOUT_MS is introduced in 7.16.2, we have 7.16.0 in tree */ #ifdef CURLOPT_TIMEOUT_MS if (timeout > 0) { - curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT_MS, timeout); + switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT_MS, timeout); } else { - curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT_MS, globals.curl_timeout); + switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT_MS, globals.curl_timeout); } #else if (timeout > 0) { - curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, timeout); + switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, timeout); } else { - curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, globals.curl_timeout / 1000); + switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, globals.curl_timeout / 1000); } #endif - curl_easy_setopt(curl_handle, CURLOPT_URL, query); - curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, file_callback); - curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &http_data); - curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-cidlookup/1.0"); + switch_curl_easy_setopt(curl_handle, CURLOPT_URL, query); + switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, file_callback); + switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &http_data); + switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-cidlookup/1.0"); - curl_easy_perform(curl_handle); - curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes); - curl_easy_cleanup(curl_handle); + switch_curl_easy_perform(curl_handle); + switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes); + switch_curl_easy_cleanup(curl_handle); if (http_data.stream.data && !zstr((char *) http_data.stream.data) && strcmp(" ", http_data.stream.data)) { @@ -852,7 +852,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_cidlookup_load) Macro expands to: switch_status_t mod_cidlookup_shutdown() */ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_cidlookup_shutdown) { - switch_event_unbind(&reload_xml_event); return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index 1513743018..5f0805c266 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -32,6 +32,7 @@ * Cesar Cepeda * Massimo Cetra * Rupa Schomaker + * Joseph Sullivan * * * mod_commands.c -- Misc. Command Module @@ -45,6 +46,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_commands_shutdown); SWITCH_MODULE_DEFINITION(mod_commands, mod_commands_load, mod_commands_shutdown, NULL); +static switch_mutex_t *reload_mutex = NULL; struct cb_helper { uint32_t row_process; @@ -1791,7 +1793,7 @@ SWITCH_STANDARD_API(status_function) return SWITCH_STATUS_SUCCESS; } -#define CTL_SYNTAX "[send_sighup|hupall|pause|resume|shutdown [cancel|elegant|asap|now|restart]|sps|sync_clock|reclaim_mem|max_sessions|min_dtmf_duration [num]|max_dtmf_duration [num]|default_dtmf_duration [num]|min_idle_cpu|loglevel [level]|debug_level [level]]" +#define CTL_SYNTAX "[send_sighup|hupall|pause [inbound|outbound]|resume [inbound|outbound]|shutdown [cancel|elegant|asap|now|restart]|sps|sync_clock|sync_clock_when_idle|reclaim_mem|max_sessions|min_dtmf_duration [num]|max_dtmf_duration [num]|default_dtmf_duration [num]|min_idle_cpu|loglevel [level]|debug_level [level]]" SWITCH_STANDARD_API(ctl_function) { int argc; @@ -1814,16 +1816,32 @@ SWITCH_STANDARD_API(ctl_function) switch_core_session_ctl(SCSC_FLUSH_DB_HANDLES, NULL); stream->write_function(stream, "+OK\n"); } else if (!strcasecmp(argv[0], "pause")) { + switch_session_ctl_t command = SCSC_PAUSE_ALL; arg = 1; - switch_core_session_ctl(SCSC_PAUSE_INBOUND, &arg); + if (argv[1]) { + if (!strcasecmp(argv[1], "inbound")) { + command = SCSC_PAUSE_INBOUND; + } else if (!strcasecmp(argv[1], "outbound")) { + command = SCSC_PAUSE_OUTBOUND; + } + } + switch_core_session_ctl(command, &arg); stream->write_function(stream, "+OK\n"); } else if (!strcasecmp(argv[0], "send_sighup")) { arg = 1; switch_core_session_ctl(SCSC_SEND_SIGHUP, &arg); stream->write_function(stream, "+OK\n"); } else if (!strcasecmp(argv[0], "resume")) { + switch_session_ctl_t command = SCSC_PAUSE_ALL; arg = 0; - switch_core_session_ctl(SCSC_PAUSE_INBOUND, &arg); + if (argv[1]) { + if (!strcasecmp(argv[1], "inbound")) { + command = SCSC_PAUSE_INBOUND; + } else if (!strcasecmp(argv[1], "outbound")) { + command = SCSC_PAUSE_OUTBOUND; + } + } + switch_core_session_ctl(command, &arg); stream->write_function(stream, "+OK\n"); } else if (!strcasecmp(argv[0], "calibrate_clock")) { switch_core_session_ctl(SCSC_CALIBRATE_CLOCK, NULL); @@ -1854,7 +1872,15 @@ SWITCH_STANDARD_API(ctl_function) switch_core_session_ctl(SCSC_SAVE_HISTORY, NULL); stream->write_function(stream, "+OK\n"); } else if (!strcasecmp(argv[0], "pause_check")) { - switch_core_session_ctl(SCSC_PAUSE_CHECK, &arg); + switch_session_ctl_t command = SCSC_PAUSE_CHECK; + if (argv[1]) { + if (!strcasecmp(argv[1], "inbound")) { + command = SCSC_PAUSE_INBOUND_CHECK; + } else if (!strcasecmp(argv[1], "outbound")) { + command = SCSC_PAUSE_OUTBOUND_CHECK; + } + } + switch_core_session_ctl(command, &arg); stream->write_function(stream, arg ? "true" : "false"); } else if (!strcasecmp(argv[0], "ready_check")) { switch_core_session_ctl(SCSC_READY_CHECK, &arg); @@ -1972,6 +1998,14 @@ SWITCH_STANDARD_API(ctl_function) arg = 0; switch_core_session_ctl(SCSC_SYNC_CLOCK, &arg); stream->write_function(stream, "+OK clock synchronized\n"); + } else if (!strcasecmp(argv[0], "sync_clock_when_idle")) { + arg = 0; + switch_core_session_ctl(SCSC_SYNC_CLOCK_WHEN_IDLE, &arg); + if (arg) { + stream->write_function(stream, "+OK clock synchronized\n"); + } else { + stream->write_function(stream, "+OK clock will synchronize when there are no more calls\n"); + } } else { stream->write_function(stream, "-ERR INVALID COMMAND\nUSAGE: fsctl %s", CTL_SYNTAX); goto end; @@ -1996,6 +2030,8 @@ SWITCH_STANDARD_API(load_function) return SWITCH_STATUS_SUCCESS; } + switch_mutex_lock(reload_mutex); + if (switch_xml_reload(&err) == SWITCH_STATUS_SUCCESS) { stream->write_function(stream, "+OK Reloading XML\n"); } @@ -2006,6 +2042,8 @@ SWITCH_STANDARD_API(load_function) stream->write_function(stream, "-ERR [%s]\n", err); } + switch_mutex_unlock(reload_mutex); + return SWITCH_STATUS_SUCCESS; } @@ -2045,12 +2083,16 @@ SWITCH_STANDARD_API(unload_function) return SWITCH_STATUS_SUCCESS; } + switch_mutex_lock(reload_mutex); + if (switch_loadable_module_unload_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) cmd, force, &err) == SWITCH_STATUS_SUCCESS) { stream->write_function(stream, "+OK\n"); } else { stream->write_function(stream, "-ERR [%s]\n", err); } + switch_mutex_unlock(reload_mutex); + return SWITCH_STATUS_SUCCESS; } @@ -2088,6 +2130,8 @@ SWITCH_STANDARD_API(reload_function) return SWITCH_STATUS_SUCCESS; } + switch_mutex_lock(reload_mutex); + if (switch_loadable_module_unload_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) cmd, force, &err) == SWITCH_STATUS_SUCCESS) { stream->write_function(stream, "+OK module unloaded\n"); } else { @@ -2104,6 +2148,8 @@ SWITCH_STANDARD_API(reload_function) stream->write_function(stream, "-ERR loading module [%s]\n", err); } + switch_mutex_unlock(reload_mutex); + return SWITCH_STATUS_SUCCESS; } @@ -2120,7 +2166,6 @@ SWITCH_STANDARD_API(reload_xml_function) #define KILL_SYNTAX " [cause]" SWITCH_STANDARD_API(kill_function) { - switch_core_session_t *ksession = NULL; char *mycmd = NULL, *kcause = NULL; switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING; @@ -2131,17 +2176,14 @@ SWITCH_STANDARD_API(kill_function) if ((kcause = strchr(mycmd, ' '))) { *kcause++ = '\0'; - } - - if (zstr(mycmd) || !(ksession = switch_core_session_locate(mycmd))) { - stream->write_function(stream, "-ERR No Such Channel!\n"); - } else { - switch_channel_t *channel = switch_core_session_get_channel(ksession); if (!zstr(kcause)) { cause = switch_channel_str2cause(kcause); - } - switch_channel_hangup(channel, cause); - switch_core_session_rwunlock(ksession); + } + } + + if (switch_ivr_kill_uuid(mycmd, cause) != SWITCH_STATUS_SUCCESS) { + stream->write_function(stream, "-ERR No Such Channel!\n"); + } else { stream->write_function(stream, "+OK\n"); } @@ -2435,12 +2477,11 @@ SWITCH_STANDARD_API(tone_detect_session_function) SWITCH_STANDARD_API(uuid_function) { - switch_uuid_t uuid; char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; - switch_uuid_get(&uuid); - switch_uuid_format(uuid_str, &uuid); - stream->write_function(stream, "%s", uuid_str); + switch_uuid_str(uuid_str, sizeof(uuid_str)); + + stream->write_function(stream, "%s", uuid_str); return SWITCH_STATUS_SUCCESS; } @@ -3006,6 +3047,44 @@ SWITCH_STANDARD_API(uuid_phone_event_function) return SWITCH_STATUS_SUCCESS; } +#define INFO_SYNTAX "" +SWITCH_STANDARD_API(uuid_send_info_function) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + char *mycmd = NULL, *argv[2] = { 0 }; + int argc = 0; + + if (!zstr(cmd) && (mycmd = strdup(cmd))) { + argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + } + + if (argc < 1) { + stream->write_function(stream, "-USAGE: %s\n", INFO_SYNTAX); + } else { + switch_core_session_message_t msg = { 0 }; + switch_core_session_t *lsession = NULL; + + msg.message_id = SWITCH_MESSAGE_INDICATE_INFO; + msg.string_array_arg[2] = argv[1]; + msg.from = __FILE__; + + if ((lsession = switch_core_session_locate(argv[0]))) { + status = switch_core_session_receive_message(lsession, &msg); + switch_core_session_rwunlock(lsession); + } + } + + if (status == SWITCH_STATUS_SUCCESS) { + stream->write_function(stream, "+OK Success\n"); + } else { + stream->write_function(stream, "-ERR Operation Failed\n"); + } + + switch_safe_free(mycmd); + + return SWITCH_STATUS_SUCCESS; +} + #define DEBUG_AUDIO_SYNTAX " " SWITCH_STANDARD_API(uuid_debug_audio_function) @@ -3412,11 +3491,16 @@ SWITCH_STANDARD_API(originate_function) uint8_t machine = 1; switch_status_t status = SWITCH_STATUS_SUCCESS; - if (session || zstr(cmd)) { + if (zstr(cmd)) { stream->write_function(stream, "-USAGE %s\n", ORIGINATE_SYNTAX); return SWITCH_STATUS_SUCCESS; } + /* log warning if part of ongoing session, as we'll block the session */ + if (session){ + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Originate can take 60 seconds to complete, and blocks the existing session. Do not confuse with a lockup.\n"); + } + mycmd = strdup(cmd); switch_assert(mycmd); argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); @@ -4078,11 +4162,11 @@ SWITCH_STANDARD_API(show_function) holder.print_title = 0; if ((cmdname = strchr(command, ' ')) && strcasecmp(cmdname, "as")) { *cmdname++ = '\0'; - switch_snprintf(sql, sizeof(sql) - 1, - "select name, syntax, description, ikey from interfaces where hostname='%s' and type = 'api' and name = '%s' order by name", + switch_snprintfv(sql, sizeof(sql), + "select name, syntax, description, ikey from interfaces where hostname='%s' and type = 'api' and name = '%q' order by name", hostname, cmdname); } else { - switch_snprintf(sql, sizeof(sql) - 1, "select name, syntax, description, ikey from interfaces where hostname='%s' and type = 'api' order by name", hostname); + switch_snprintfv(sql, sizeof(sql), "select name, syntax, description, ikey from interfaces where hostname='%q' and type = 'api' order by name", hostname); } } else if (!strcasecmp(command, "nat_map")) { switch_snprintf(sql, sizeof(sql) - 1, @@ -5235,6 +5319,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) *module_interface = switch_loadable_module_create_module_interface(pool, modname); switch_thread_rwlock_create(&bgapi_rwlock, pool); + switch_mutex_init(&reload_mutex, SWITCH_MUTEX_NESTED, pool); + SWITCH_ADD_API(commands_api_interface, "acl", "compare an ip to an acl list", acl_function, " "); SWITCH_ADD_API(commands_api_interface, "alias", "Alias", alias_function, ALIAS_SYNTAX); @@ -5326,6 +5412,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) SWITCH_ADD_API(commands_api_interface, "uuid_getvar", "uuid_getvar", uuid_getvar_function, GETVAR_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_hold", "hold", uuid_hold_function, HOLD_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_kill", "Kill Channel", kill_function, KILL_SYNTAX); + SWITCH_ADD_API(commands_api_interface, "uuid_send_info", "Send info to the endpoint", uuid_send_info_function, INFO_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_outgoing_answer", "Answer Outgoing Channel", outgoing_answer_function, OUTGOING_ANSWER_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_limit", "Increase limit resource", uuid_limit_function, LIMIT_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_limit_release", "Release limit resource", uuid_limit_release_function, LIMIT_RELEASE_SYNTAX); @@ -5374,13 +5461,19 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) switch_console_set_complete("add fsctl max_sessions"); switch_console_set_complete("add fsctl min_dtmf_duration"); switch_console_set_complete("add fsctl pause"); + switch_console_set_complete("add fsctl pause inbound"); + switch_console_set_complete("add fsctl pause outbound"); switch_console_set_complete("add fsctl reclaim_mem"); switch_console_set_complete("add fsctl resume"); + switch_console_set_complete("add fsctl resume inbound"); + switch_console_set_complete("add fsctl resume outbound"); switch_console_set_complete("add fsctl calibrate_clock"); switch_console_set_complete("add fsctl crash"); switch_console_set_complete("add fsctl verbose_events"); switch_console_set_complete("add fsctl save_history"); switch_console_set_complete("add fsctl pause_check"); + switch_console_set_complete("add fsctl pause_check inbound"); + switch_console_set_complete("add fsctl pause_check outbound"); switch_console_set_complete("add fsctl ready_check"); switch_console_set_complete("add fsctl shutdown_check"); switch_console_set_complete("add fsctl shutdown"); @@ -5452,6 +5545,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) switch_console_set_complete("add uuid_flush_dtmf ::console::list_uuid"); switch_console_set_complete("add uuid_getvar ::console::list_uuid"); switch_console_set_complete("add uuid_hold ::console::list_uuid"); + switch_console_set_complete("add uuid_send_info ::console::list_uuid"); switch_console_set_complete("add uuid_jitterbuffer ::console::list_uuid"); switch_console_set_complete("add uuid_kill ::console::list_uuid"); switch_console_set_complete("add uuid_outgoing_answer ::console::list_uuid"); diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 53d2f3f34a..613202aa8c 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -43,6 +43,16 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_conference_load); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_conference_shutdown); SWITCH_MODULE_DEFINITION(mod_conference, mod_conference_load, mod_conference_shutdown, NULL); +typedef struct conference_cdr_node_s { + switch_caller_profile_t *cp; + char *record_path; + switch_time_t join_time; + switch_time_t leave_time; + struct conference_cdr_node_s *next; +} conference_cdr_node_t; + + + typedef enum { CONF_SILENT_REQ = (1 << 0), CONF_SILENT_DONE = (1 << 1) @@ -132,7 +142,7 @@ typedef enum { MFLAG_ITHREAD = (1 << 4), MFLAG_NOCHANNEL = (1 << 5), MFLAG_INTREE = (1 << 6), - MFLAG_WASTE_BANDWIDTH = (1 << 7), + MFLAG_WASTE_FLAG = (1 << 7), MFLAG_FLUSH_BUFFER = (1 << 8), MFLAG_ENDCONF = (1 << 9), MFLAG_HAS_AUDIO = (1 << 10), @@ -159,7 +169,7 @@ typedef enum { CFLAG_BRIDGE_TO = (1 << 6), CFLAG_WAIT_MOD = (1 << 7), CFLAG_VID_FLOOR = (1 << 8), - CFLAG_WASTE_BANDWIDTH = (1 << 9), + CFLAG_WASTE_FLAG = (1 << 9), CFLAG_OUTCALL = (1 << 10), CFLAG_INHASH = (1 << 11), CFLAG_EXIT_SOUND = (1 << 12), @@ -227,6 +237,12 @@ typedef struct conf_xml_cfg { switch_xml_t controls; } conf_xml_cfg_t; +struct vid_helper { + conference_member_t *member_a; + conference_member_t *member_b; + int up; +}; + /* Conference Object */ typedef struct conference_obj { char *name; @@ -252,16 +268,19 @@ typedef struct conference_obj { char *sound_prefix; char *special_announce; char *auto_record; + char *record_filename; uint32_t terminate_on_silence; uint32_t max_members; char *maxmember_sound; uint32_t announce_count; char *pin; + char *mpin; char *pin_sound; char *bad_pin_sound; char *profile_name; char *domain; char *caller_controls; + char *moderator_controls; uint32_t flags; member_flag_t mflags; switch_call_cause_t bridge_hangup_cause; @@ -283,10 +302,13 @@ typedef struct conference_obj { switch_speech_handle_t *sh; switch_byte_t *not_talking_buf; uint32_t not_talking_buf_len; + int pin_retries; int comfort_noise_level; int is_recording; int record_count; int video_running; + int ivr_dtmf_timeout; + int ivr_input_timeout; uint32_t eflags; uint32_t verbose_events; int end_count; @@ -303,6 +325,11 @@ typedef struct conference_obj { char *uuid_str; uint32_t originating; switch_call_cause_t cancel_cause; + conference_cdr_node_t *cdr_nodes; + switch_time_t start_time; + switch_time_t end_time; + char *log_dir; + struct vid_helper vh[2]; } conference_obj_t; /* Relationship with another member */ @@ -330,6 +357,7 @@ struct conference_member { switch_mutex_t *audio_in_mutex; switch_mutex_t *audio_out_mutex; switch_mutex_t *read_mutex; + switch_mutex_t *fnode_mutex; switch_thread_rwlock_t *rwlock; switch_codec_implementation_t read_impl; switch_codec_implementation_t orig_read_impl; @@ -364,6 +392,8 @@ struct conference_member { uint32_t avg_tally; struct conference_member *next; switch_ivr_dmachine_t *dmachine; + conference_cdr_node_t *cdr_node; + char *kicked_sound; }; /* Record Node */ @@ -409,6 +439,7 @@ static switch_status_t conference_say(conference_obj_t *conference, const char * static void conference_list(conference_obj_t *conference, switch_stream_handle_t *stream, char *delim); static conference_obj_t *conference_find(char *name); static void member_bind_controls(conference_member_t *member, const char *controls); +static void conference_send_presence(conference_obj_t *conference); SWITCH_STANDARD_API(conf_api_main); @@ -446,7 +477,7 @@ typedef switch_status_t (*conf_api_args_cmd_t) (conference_obj_t *, switch_strea typedef switch_status_t (*conf_api_member_cmd_t) (conference_member_t *, switch_stream_handle_t *, void *); typedef switch_status_t (*conf_api_text_cmd_t) (conference_obj_t *, switch_stream_handle_t *, const char *); -static void conference_member_itterator(conference_obj_t *conference, switch_stream_handle_t *stream, conf_api_member_cmd_t pfncallback, void *data); +static void conference_member_itterator(conference_obj_t *conference, switch_stream_handle_t *stream, uint8_t non_mod, conf_api_member_cmd_t pfncallback, void *data); static switch_status_t conf_api_sub_mute(conference_member_t *member, switch_stream_handle_t *stream, void *data); static switch_status_t conf_api_sub_unmute(conference_member_t *member, switch_stream_handle_t *stream, void *data); static switch_status_t conf_api_sub_deaf(conference_member_t *member, switch_stream_handle_t *stream, void *data); @@ -461,6 +492,173 @@ static switch_status_t conference_add_event_member_data(conference_member_t *mem //#define lock_member(_member) switch_mutex_lock(_member->write_mutex) //#define unlock_member(_member) switch_mutex_unlock(_member->write_mutex) + +static void conference_cdr_del(conference_member_t *member) +{ + member->cdr_node->leave_time = switch_epoch_time_now(NULL); +} + +static void conference_cdr_add(conference_member_t *member) +{ + conference_cdr_node_t *np; + switch_caller_profile_t *cp; + switch_channel_t *channel; + + np = switch_core_alloc(member->conference->pool, sizeof(*np)); + + np->next = member->conference->cdr_nodes; + member->conference->cdr_nodes = member->cdr_node = np; + member->cdr_node->join_time = switch_epoch_time_now(NULL); + + if (!member->session) { + member->cdr_node->record_path = switch_core_strdup(member->conference->pool, member->rec_path); + return; + } + + channel = switch_core_session_get_channel(member->session); + + if (!(cp = switch_channel_get_caller_profile(channel))) { + return; + } + + member->cdr_node->cp = switch_caller_profile_dup(member->conference->pool, cp); +} + +static void conference_cdr_render(conference_obj_t *conference) +{ + switch_xml_t cdr, x_ptr, x_member, x_members, x_conference, x_cp; + conference_cdr_node_t *np; + int cdr_off = 0, conf_off = 0; + char str[512]; + char *path, *xml_text; + int fd; + + if (zstr(conference->log_dir)) return; + + if (!conference->cdr_nodes) return; + + if (!(cdr = switch_xml_new("cdr"))) { + abort(); + } + + if (!(x_conference = switch_xml_add_child_d(cdr, "conference", cdr_off++))) { + abort(); + } + + if (!(x_ptr = switch_xml_add_child_d(x_conference, "name", conf_off++))) { + abort(); + } + switch_xml_set_txt_d(x_ptr, conference->name); + + if (!(x_ptr = switch_xml_add_child_d(x_conference, "rate", conf_off++))) { + abort(); + } + switch_snprintf(str, sizeof(str), "%d", conference->rate); + switch_xml_set_txt_d(x_ptr, str); + + if (!(x_ptr = switch_xml_add_child_d(x_conference, "interval", conf_off++))) { + abort(); + } + switch_snprintf(str, sizeof(str), "%d", conference->interval); + switch_xml_set_txt_d(x_ptr, str); + + + if (!(x_ptr = switch_xml_add_child_d(x_conference, "start_time", conf_off++))) { + abort(); + } + switch_xml_set_attr_d(x_ptr, "type", "UNIX-epoch"); + switch_snprintf(str, sizeof(str), "%ld", (long)conference->start_time); + switch_xml_set_txt_d(x_ptr, str); + + + if (!(x_ptr = switch_xml_add_child_d(x_conference, "end_time", conf_off++))) { + abort(); + } + switch_xml_set_attr_d(x_ptr, "type", "UNIX-epoch"); + switch_snprintf(str, sizeof(str), "%ld", (long)conference->end_time); + switch_xml_set_txt_d(x_ptr, str); + + + if (!(x_members = switch_xml_add_child_d(x_conference, "members", conf_off++))) { + abort(); + } + + + for (np = conference->cdr_nodes; np; np = np->next) { + int member_off = 0; + + + if (!(x_member = switch_xml_add_child_d(x_members, "member", conf_off++))) { + abort(); + } + + switch_xml_set_attr_d(x_member, "type", np->cp ? "caller" : "recording_node"); + + if (!(x_ptr = switch_xml_add_child_d(x_member, "join_time", member_off++))) { + abort(); + } + switch_xml_set_attr_d(x_ptr, "type", "UNIX-epoch"); + switch_snprintf(str, sizeof(str), "%ld", (long) np->join_time); + switch_xml_set_txt_d(x_ptr, str); + + + if (!(x_ptr = switch_xml_add_child_d(x_member, "leave_time", member_off++))) { + abort(); + } + switch_xml_set_attr_d(x_ptr, "type", "UNIX-epoch"); + switch_snprintf(str, sizeof(str), "%ld", (long) np->leave_time); + switch_xml_set_txt_d(x_ptr, str); + + if (np->cp) { + if (!(x_cp = switch_xml_add_child_d(x_member, "caller_profile", member_off++))) { + abort(); + } + switch_ivr_set_xml_profile_data(x_cp, np->cp, 0); + } + + if (!zstr(np->record_path)) { + if (!(x_ptr = switch_xml_add_child_d(x_member, "record_path", member_off++))) { + abort(); + } + switch_xml_set_txt_d(x_ptr, np->record_path); + } + } + + + xml_text = switch_xml_toxml(cdr, SWITCH_TRUE); + + + path = switch_mprintf("%s%s%s.cdr.xml", conference->log_dir, SWITCH_PATH_SEPARATOR, conference->uuid_str); + + + +#ifdef _MSC_VER + if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) > -1) { +#else + if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) > -1) { +#endif + int wrote; + wrote = write(fd, xml_text, (unsigned) strlen(xml_text)); + wrote++; + close(fd); + fd = -1; + } else { + char ebuf[512] = { 0 }; +#ifdef WIN32 + strerror_s(ebuf, sizeof(ebuf), errno); +#else + strerror_r(errno, ebuf, sizeof(ebuf)); +#endif + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error writing [%s][%s]\n", path, ebuf); + } + + + switch_safe_free(path); + switch_safe_free(xml_text); +} + + + static switch_status_t conference_add_event_data(conference_obj_t *conference, switch_event_t *event) { switch_status_t status = SWITCH_STATUS_SUCCESS; @@ -571,12 +769,21 @@ static conference_member_t *conference_member_get(conference_obj_t *conference, } } - if (member && !switch_test_flag(member, MFLAG_INTREE)) { - member = NULL; + if (member) { + if (!switch_test_flag(member, MFLAG_INTREE) || + switch_test_flag(member, MFLAG_KICKED) || + (member->session && !switch_channel_up(switch_core_session_get_channel(member->session)))) { + + /* member is kicked or hanging up so forget it */ + member = NULL; + } } if (member) { - switch_thread_rwlock_rdlock(member->rwlock); + if (switch_thread_rwlock_tryrdlock(member->rwlock) != SWITCH_STATUS_SUCCESS) { + /* if you cant readlock it's way to late to do anything */ + member = NULL; + } } switch_mutex_unlock(conference->member_mutex); @@ -687,37 +894,27 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe conference->members = member; switch_set_flag_locked(member, MFLAG_INTREE); switch_mutex_unlock(conference->member_mutex); + conference_cdr_add(member); if (!switch_test_flag(member, MFLAG_NOCHANNEL)) { conference->count++; if (switch_test_flag(member, MFLAG_ENDCONF)) { - if (conference->end_count++); + if (conference->end_count++) {}; } - if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", CONF_CHAT_PROTO); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", conference->name); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", conference->name, conference->domain); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "Active (%d caller%s)", conference->count, conference->count == 1 ? "" : "s"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", conference->name); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_ROUTING"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", conference->count == 1 ? "early" : "confirmed"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-call-direction", conference->count == 1 ? "outbound" : "inbound"); - switch_event_fire(&event); - } + conference_send_presence(conference); + channel = switch_core_session_get_channel(member->session); + switch_channel_set_variable_printf(channel, "conference_member_id", "%d", member->id); + switch_channel_set_variable_printf(channel, "conference_moderator", "%s", switch_test_flag(member, MFLAG_MOD) ? "true" : "false"); + switch_channel_set_variable(channel, "conference_recording", conference->record_filename); + switch_channel_set_variable(channel, CONFERENCE_UUID_VARIABLE, conference->uuid_str); + if (switch_test_flag(conference, CFLAG_WAIT_MOD) && switch_test_flag(member, MFLAG_MOD)) { switch_clear_flag(conference, CFLAG_WAIT_MOD); } - channel = switch_core_session_get_channel(member->session); - switch_channel_set_variable_printf(channel, "conference_member_id", "%d", member->id); - switch_channel_set_variable(channel, CONFERENCE_UUID_VARIABLE, conference->uuid_str); - if (conference->count > 1) { if (conference->moh_sound && !switch_test_flag(conference, CFLAG_WAIT_MOD)) { /* stop MoH if any */ @@ -787,12 +984,17 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe switch_channel_clear_app_flag_key("conf_silent", channel, CONF_SILENT_REQ); switch_channel_set_app_flag_key("conf_silent", channel, CONF_SILENT_DONE); - switch_ivr_dmachine_create(&member->dmachine, "mod_conference", NULL, 500, 0, NULL, NULL, NULL); + switch_ivr_dmachine_create(&member->dmachine, "mod_conference", NULL, + conference->ivr_dtmf_timeout, conference->ivr_input_timeout, NULL, NULL, NULL); controls = switch_channel_get_variable(channel, "conference_controls"); if (zstr(controls)) { - controls = conference->caller_controls; + if (!switch_test_flag(member, MFLAG_MOD) || !conference->moderator_controls) { + controls = conference->caller_controls; + } else { + controls = conference->moderator_controls; + } } if (zstr(controls)) { @@ -836,6 +1038,11 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe lock_member(member); + + + conference_cdr_del(member); + + member_fnode = member->fnode; member_sh = member->sh; member->fnode = NULL; @@ -905,20 +1112,7 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe } - if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", CONF_CHAT_PROTO); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", conference->name); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", conference->name, conference->domain); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "Active (%d caller%s)", conference->count, conference->count == 1 ? "" : "s"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", conference->name); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_ROUTING"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", conference->count == 1 ? "early" : "confirmed"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", conference->count == 1 ? "outbound" : "inbound"); - switch_event_fire(&event); - } + conference_send_presence(conference); if ((conference->min && switch_test_flag(conference, CFLAG_ENFORCE_MIN) && conference->count < conference->min) || (switch_test_flag(conference, CFLAG_DYNAMIC) && conference->count == 0)) { @@ -955,50 +1149,52 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe return status; } -struct vid_helper { - conference_member_t *member_a; - conference_member_t *member_b; - int up; -}; - /* Thread bridging video between two members, there will be two threads if video briding is used */ static void *SWITCH_THREAD_FUNC conference_video_bridge_thread_run(switch_thread_t *thread, void *obj) { struct vid_helper *vh = obj; - switch_channel_t *channel_a = switch_core_session_get_channel(vh->member_a->session); - switch_channel_t *channel_b = switch_core_session_get_channel(vh->member_b->session); + switch_core_session_t *session_a = vh->member_a->session; + switch_core_session_t *session_b = vh->member_b->session; + switch_channel_t *channel_a = switch_core_session_get_channel(session_a); + switch_channel_t *channel_b = switch_core_session_get_channel(session_b); switch_status_t status; switch_frame_t *read_frame; + conference_obj_t *conference = vh->member_a->conference; + + switch_thread_rwlock_rdlock(conference->rwlock); + switch_thread_rwlock_rdlock(vh->member_a->rwlock); + switch_thread_rwlock_rdlock(vh->member_b->rwlock); + /* Acquire locks for both sessions so the helper object and member structures don't get destroyed before we exit */ - if (switch_core_session_read_lock(vh->member_a->session) != SWITCH_STATUS_SUCCESS) { - return NULL; - } + switch_core_session_read_lock(session_a); + switch_core_session_read_lock(session_b); - if (switch_core_session_read_lock(vh->member_b->session) != SWITCH_STATUS_SUCCESS) { - switch_core_session_rwunlock(vh->member_a->session); - return NULL; - } - vh->up = 1; - while (switch_test_flag(vh->member_a, MFLAG_RUNNING) && switch_test_flag(vh->member_b, MFLAG_RUNNING) && + while (vh->up == 1 && switch_test_flag(vh->member_a, MFLAG_RUNNING) && switch_test_flag(vh->member_b, MFLAG_RUNNING) && switch_channel_ready(channel_a) && switch_channel_ready(channel_b)) { - status = switch_core_session_read_video_frame(vh->member_a->session, &read_frame, SWITCH_IO_FLAG_NONE, 0); - if (!SWITCH_READ_ACCEPTABLE(status)) { + + status = switch_core_session_read_video_frame(session_a, &read_frame, SWITCH_IO_FLAG_NONE, 0); + if (!SWITCH_READ_ACCEPTABLE(status)) { + break; + } + + if (!switch_test_flag(read_frame, SFF_CNG)) { + if (switch_core_session_write_video_frame(session_b, read_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) { break; } - - if (!switch_test_flag(read_frame, SFF_CNG)) { - if (switch_core_session_write_video_frame(vh->member_b->session, read_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) { - break; - } - } + } } - - switch_core_session_rwunlock(vh->member_a->session); - switch_core_session_rwunlock(vh->member_b->session); + + switch_thread_rwlock_unlock(vh->member_b->rwlock); + switch_thread_rwlock_unlock(vh->member_a->rwlock); + + switch_core_session_rwunlock(session_a); + switch_core_session_rwunlock(session_b); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s video thread ended.\n", switch_channel_get_name(channel_a)); + + switch_thread_rwlock_unlock(conference->rwlock); vh->up = 0; return NULL; @@ -1178,19 +1374,19 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v if (imember->session) { if (switch_channel_test_flag(switch_core_session_get_channel(imember->session), CF_VIDEO)) { members_with_video++; + + if (switch_test_flag(imember, MFLAG_VIDEO_BRIDGE)) { + if (!video_bridge_members[0]) { + video_bridge_members[0] = imember; + } else { + video_bridge_members[1] = imember; + } + } } if (switch_test_flag(imember, MFLAG_NOMOH)) { nomoh++; } - - if (switch_test_flag(imember, MFLAG_VIDEO_BRIDGE)) { - if (!video_bridge_members[0]) { - video_bridge_members[0] = imember; - } else { - video_bridge_members[1] = imember; - } - } } switch_clear_flag_locked(imember, MFLAG_HAS_AUDIO); @@ -1242,6 +1438,13 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v launch_conference_record_thread(conference, rfile); if (rfile != conference->auto_record) { switch_safe_free(rfile); + } else { + conference->record_filename = switch_core_strdup(conference->pool, conference->auto_record); + } + /* Set the conference recording variable for each member */ + for (omember = conference->members; omember; omember = omember->next) { + channel = switch_core_session_get_channel(omember->session); + switch_channel_set_variable(channel, "conference_recording", conference->record_filename); } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Auto Record Failed. No members in conference.\n"); @@ -1249,10 +1452,14 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v } - if (members_with_video && conference->video_running != 1) { - if (!switch_test_flag(conference, CFLAG_VIDEO_BRIDGE)) { - launch_conference_video_thread(conference); - } else if (video_bridge_members[0] && video_bridge_members[1]){ + if (members_with_video) { + if (conference->video_running != 1) { + if (!switch_test_flag(conference, CFLAG_VIDEO_BRIDGE)) { + launch_conference_video_thread(conference); + } + } + + if (conference->vh[0].up != 1 && conference->vh[1].up != 1 && video_bridge_members[0] && video_bridge_members[1]){ launch_conference_video_bridge_thread(video_bridge_members[0], video_bridge_members[1]); } } @@ -1333,17 +1540,6 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v } } - if (switch_test_flag(conference, CFLAG_WASTE_BANDWIDTH) && !has_file_data) { - file_sample_len = bytes / 2; - - if (conference->comfort_noise_level) { - switch_generate_sln_silence((int16_t *) file_frame, file_sample_len, conference->comfort_noise_level); - } else { - memset(file_frame, 255, bytes); - } - has_file_data = 1; - } - if (ready || has_file_data) { /* Use more bits in the main_frame to preserve the exact sum of the audio samples. */ int main_frame[SWITCH_RECOMMENDED_BUFFER_SIZE / 2] = { 0 }; @@ -1416,8 +1612,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v continue; } - if (!switch_test_flag(omember, MFLAG_CAN_HEAR) && !switch_test_flag(omember, MFLAG_WASTE_BANDWIDTH) - && !switch_test_flag(conference, CFLAG_WASTE_BANDWIDTH)) { + if (!switch_test_flag(omember, MFLAG_CAN_HEAR)) { continue; } @@ -1511,21 +1706,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v } } - if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", CONF_CHAT_PROTO); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", conference->name); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", conference->name, conference->domain); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "Inactive"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "idle"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", conference->name); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_HANGUP"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "terminated"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", "inbound"); - switch_event_fire(&event); - } + conference_send_presence(conference); switch_mutex_lock(conference->mutex); conference_stop_file(conference, FILE_STOP_ASYNC); @@ -1582,6 +1763,18 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v switch_mutex_unlock(conference->member_mutex); switch_mutex_unlock(conference->mutex); + if (conference->vh[0].up == 1) { + conference->vh[0].up = -1; + } + + if (conference->vh[1].up == 1) { + conference->vh[1].up = -1; + } + + while (conference->vh[0].up || conference->vh[1].up) { + switch_cond_next(); + } + if (conference->video_running == 1) { conference->video_running = -1; while (conference->video_running) { @@ -1610,6 +1803,9 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v conference->sh = NULL; } + conference->end_time = switch_epoch_time_now(NULL); + conference_cdr_render(conference); + if (conference->pool) { switch_memory_pool_t *pool = conference->pool; switch_core_destroy_memory_pool(&pool); @@ -1661,6 +1857,9 @@ static void conference_loop_fn_lock_toggle(conference_member_t *member, caller_c if (member == NULL) return; + if (switch_test_flag(member->conference, CFLAG_WAIT_MOD) && !switch_test_flag(member, MFLAG_MOD) ) + return; + if (!switch_test_flag(member->conference, CFLAG_LOCKED)) { if (member->conference->is_locked_sound) { conference_play_file(member->conference, member->conference->is_locked_sound, CONF_DEFAULT_LEADIN, NULL, 0); @@ -2479,8 +2678,11 @@ static void member_add_file_data(conference_member_t *member, int16_t *data, swi switch_size_t file_sample_len = file_data_len / 2; int16_t file_frame[SWITCH_RECOMMENDED_BUFFER_SIZE / 2] = { 0 }; + + switch_mutex_lock(member->fnode_mutex); + if (!member->fnode) { - return; + goto done; } /* if we are done, clean it up */ @@ -2545,6 +2747,10 @@ static void member_add_file_data(conference_member_t *member, int16_t *data, swi } } } + + done: + + switch_mutex_unlock(member->fnode_mutex); } @@ -2629,7 +2835,10 @@ static void conference_loop_output(conference_member_t *member) const char *profile = switch_channel_get_variable(channel, "conference_auto_outcall_profile"); const char *ann = switch_channel_get_variable(channel, "conference_auto_outcall_announce"); const char *prefix = switch_channel_get_variable(channel, "conference_auto_outcall_prefix"); + const char *maxwait = switch_channel_get_variable(channel, "conference_auto_outcall_maxwait"); int to = 60; + int wait_sec = 2; + int loops = 0; if (ann && !switch_channel_test_app_flag_key("conf_silent", channel, CONF_SILENT_REQ)) { member->conference->special_announce = switch_core_strdup(member->conference->pool, ann); @@ -2664,10 +2873,20 @@ static void conference_loop_output(conference_member_t *member) switch_safe_free(cpstr); } + if (maxwait) { + int tmp = atoi(maxwait); + if (tmp > 0) { + wait_sec = tmp; + } + } + + + loops = wait_sec * 10; + switch_channel_set_app_flag(channel, CF_APP_TAGGED); do { - switch_ivr_sleep(member->session, 500, SWITCH_TRUE, NULL); - } while(switch_channel_up(channel) && member->conference->originating); + switch_ivr_sleep(member->session, 100, SWITCH_TRUE, NULL); + } while(switch_channel_up(channel) && (member->conference->originating && --loops)); switch_channel_clear_app_flag(channel, CF_APP_TAGGED); if (!switch_channel_ready(channel)) { @@ -2806,22 +3025,21 @@ static void conference_loop_output(conference_member_t *member) switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); break; } - } else if (!switch_test_flag(member->conference, CFLAG_WASTE_BANDWIDTH)) { - if (switch_test_flag(member, MFLAG_WASTE_BANDWIDTH)) { - if (member->conference->comfort_noise_level) { - switch_generate_sln_silence(write_frame.data, samples, member->conference->comfort_noise_level); - } else { - memset(write_frame.data, 255, bytes); - } - - write_frame.datalen = bytes; - write_frame.samples = samples; - write_frame.timestamp = timer.samplecount; - - if (switch_core_session_write_frame(member->session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) { - switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); - break; - } + } else { + + if (member->conference->comfort_noise_level) { + switch_generate_sln_silence(write_frame.data, samples, member->conference->comfort_noise_level); + } else { + memset(write_frame.data, 255, bytes); + } + + write_frame.datalen = bytes; + write_frame.samples = samples; + write_frame.timestamp = timer.samplecount; + + if (switch_core_session_write_frame(member->session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) { + switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + break; } } @@ -2961,6 +3179,7 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th switch_mutex_init(&member->write_mutex, SWITCH_MUTEX_NESTED, rec->pool); switch_mutex_init(&member->flag_mutex, SWITCH_MUTEX_NESTED, rec->pool); + switch_mutex_init(&member->fnode_mutex, SWITCH_MUTEX_NESTED, rec->pool); switch_mutex_init(&member->audio_in_mutex, SWITCH_MUTEX_NESTED, rec->pool); switch_mutex_init(&member->audio_out_mutex, SWITCH_MUTEX_NESTED, rec->pool); switch_mutex_init(&member->read_mutex, SWITCH_MUTEX_NESTED, rec->pool); @@ -3093,10 +3312,12 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th switch_mutex_unlock(member->audio_out_mutex); } - + conference->is_recording = 0; + switch_safe_free(data_buf); switch_core_timer_destroy(&timer); conference_del_member(conference, member); + switch_buffer_destroy(&member->audio_buffer); switch_buffer_destroy(&member->mux_buffer); switch_clear_flag_locked(member, MFLAG_RUNNING); @@ -3170,7 +3391,8 @@ static uint32_t conference_member_stop_file(conference_member_t *member, file_st if (member == NULL) return count; - lock_member(member); + + switch_mutex_lock(member->fnode_mutex); if (stop == FILE_STOP_ALL) { for (nptr = member->fnode; nptr; nptr = nptr->next) { @@ -3184,7 +3406,7 @@ static uint32_t conference_member_stop_file(conference_member_t *member, file_st } } - unlock_member(member); + switch_mutex_unlock(member->fnode_mutex); return count; } @@ -3348,7 +3570,7 @@ static switch_status_t conference_member_play_file(conference_member_t *member, conference_file_node_t *fnode, *nptr = NULL; switch_memory_pool_t *pool; - if (member == NULL || file == NULL) + if (member == NULL || file == NULL || switch_test_flag(member, MFLAG_KICKED)) return status; if ((expanded = switch_channel_expand_variables(switch_core_session_get_channel(member->session), file)) != file) { @@ -3401,14 +3623,14 @@ static switch_status_t conference_member_play_file(conference_member_t *member, fnode->file = switch_core_strdup(fnode->pool, file); /* Queue the node */ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG, "Queueing file '%s' for play\n", file); - lock_member(member); + switch_mutex_lock(member->fnode_mutex); for (nptr = member->fnode; nptr && nptr->next; nptr = nptr->next); if (nptr) { nptr->next = fnode; } else { member->fnode = fnode; } - unlock_member(member); + switch_mutex_unlock(member->fnode_mutex); status = SWITCH_STATUS_SUCCESS; done: @@ -3466,7 +3688,7 @@ static switch_status_t conference_member_say(conference_member_t *member, char * } /* Queue the node */ - lock_member(member); + switch_mutex_lock(member->fnode_mutex); for (nptr = member->fnode; nptr && nptr->next; nptr = nptr->next); if (nptr) { @@ -3492,7 +3714,7 @@ static switch_status_t conference_member_say(conference_member_t *member, char * } switch_core_speech_feed_tts(fnode->sh, text, &flags); - unlock_member(member); + switch_mutex_unlock(member->fnode_mutex); status = SWITCH_STATUS_SUCCESS; @@ -3588,7 +3810,7 @@ static switch_status_t conference_say(conference_obj_t *conference, const char * } /* execute a callback for every member of the conference */ -static void conference_member_itterator(conference_obj_t *conference, switch_stream_handle_t *stream, conf_api_member_cmd_t pfncallback, void *data) +static void conference_member_itterator(conference_obj_t *conference, switch_stream_handle_t *stream, uint8_t non_mod, conf_api_member_cmd_t pfncallback, void *data) { conference_member_t *member = NULL; @@ -3598,9 +3820,13 @@ static void conference_member_itterator(conference_obj_t *conference, switch_str switch_mutex_lock(conference->member_mutex); for (member = conference->members; member; member = member->next) { - if (member->session && !switch_test_flag(member, MFLAG_NOCHANNEL)) { - pfncallback(member, stream, data); - } + if (!(non_mod && switch_test_flag(member, MFLAG_MOD))) { + if (member->session && !switch_test_flag(member, MFLAG_NOCHANNEL)) { + pfncallback(member, stream, data); + } + } else { + stream->write_function(stream, "Skipping moderator (member id %d).\n", member->id); + } } switch_mutex_unlock(conference->member_mutex); } @@ -3895,6 +4121,10 @@ static switch_status_t conf_api_sub_kick(conference_member_t *member, switch_str switch_set_flag_locked(member, MFLAG_KICKED); switch_core_session_kill_channel(member->session, SWITCH_SIG_BREAK); + if (data && member->session) { + member->kicked_sound = switch_core_session_strdup(member->session, (char *) data); + } + if (stream != NULL) { stream->write_function(stream, "OK kicked %u\n", member->id); } @@ -4852,6 +5082,15 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc return ret_status; } +static switch_status_t conf_api_sub_check_record(conference_obj_t *conference, switch_stream_handle_t *stream, int arc, char **argv) +{ + if (conference->is_recording) { + stream->write_function(stream, "Record file %s\n", conference->record_filename); + } else { + stream->write_function(stream, "Conference is not being recorded.\n"); + } + return SWITCH_STATUS_SUCCESS; +} static switch_status_t conf_api_sub_record(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv) { @@ -4862,6 +5101,7 @@ static switch_status_t conf_api_sub_record(conference_obj_t *conference, switch_ return SWITCH_STATUS_GENERR; stream->write_function(stream, "Record file %s\n", argv[2]); + conference->record_filename = switch_core_strdup(conference->pool, argv[2]); conference->record_count++; launch_conference_record_thread(conference, argv[2]); return SWITCH_STATUS_SUCCESS; @@ -4906,7 +5146,11 @@ static switch_status_t conf_api_sub_pin(conference_obj_t *conference, switch_str switch_assert(conference != NULL); switch_assert(stream != NULL); - if ((argc == 3) && (!strcmp(argv[1], "pin"))) { + if ((argc == 4) && (!strcmp(argv[2], "mod"))) { + conference->mpin = switch_core_strdup(conference->pool, argv[3]); + stream->write_function(stream, "Moderator Pin for conference %s set: %s\n", argv[0], conference->mpin); + return SWITCH_STATUS_SUCCESS; + } else if ((argc == 3) && (!strcmp(argv[1], "pin"))) { conference->pin = switch_core_strdup(conference->pool, argv[2]); stream->write_function(stream, "Pin for conference %s set: %s\n", argv[0], conference->pin); return SWITCH_STATUS_SUCCESS; @@ -4952,20 +5196,20 @@ typedef enum { static api_command_t conf_api_sub_commands[] = { {"list", (void_fn_t) & conf_api_sub_list, CONF_API_SUB_ARGS_SPLIT, "list", "[delim ]"}, {"xml_list", (void_fn_t) & conf_api_sub_xml_list, CONF_API_SUB_ARGS_SPLIT, "xml_list", ""}, - {"energy", (void_fn_t) & conf_api_sub_energy, CONF_API_SUB_MEMBER_TARGET, "energy", " []"}, - {"volume_in", (void_fn_t) & conf_api_sub_volume_in, CONF_API_SUB_MEMBER_TARGET, "volume_in", " []"}, - {"volume_out", (void_fn_t) & conf_api_sub_volume_out, CONF_API_SUB_MEMBER_TARGET, "volume_out", " []"}, + {"energy", (void_fn_t) & conf_api_sub_energy, CONF_API_SUB_MEMBER_TARGET, "energy", " []"}, + {"volume_in", (void_fn_t) & conf_api_sub_volume_in, CONF_API_SUB_MEMBER_TARGET, "volume_in", " []"}, + {"volume_out", (void_fn_t) & conf_api_sub_volume_out, CONF_API_SUB_MEMBER_TARGET, "volume_out", " []"}, {"play", (void_fn_t) & conf_api_sub_play, CONF_API_SUB_ARGS_SPLIT, "play", " [async|]"}, {"say", (void_fn_t) & conf_api_sub_say, CONF_API_SUB_ARGS_AS_ONE, "say", ""}, {"saymember", (void_fn_t) & conf_api_sub_saymember, CONF_API_SUB_ARGS_AS_ONE, "saymember", " "}, {"stop", (void_fn_t) & conf_api_sub_stop, CONF_API_SUB_ARGS_SPLIT, "stop", "<[current|all|async|last]> []"}, - {"dtmf", (void_fn_t) & conf_api_sub_dtmf, CONF_API_SUB_MEMBER_TARGET, "dtmf", "<[member_id|all|last]> "}, - {"kick", (void_fn_t) & conf_api_sub_kick, CONF_API_SUB_MEMBER_TARGET, "kick", "<[member_id|all|last]>"}, - {"hup", (void_fn_t) & conf_api_sub_hup, CONF_API_SUB_MEMBER_TARGET, "hup", "<[member_id|all|last]>"}, - {"mute", (void_fn_t) & conf_api_sub_mute, CONF_API_SUB_MEMBER_TARGET, "mute", "<[member_id|all]|last>"}, - {"unmute", (void_fn_t) & conf_api_sub_unmute, CONF_API_SUB_MEMBER_TARGET, "unmute", "<[member_id|all]|last>"}, - {"deaf", (void_fn_t) & conf_api_sub_deaf, CONF_API_SUB_MEMBER_TARGET, "deaf", "<[member_id|all]|last>"}, - {"undeaf", (void_fn_t) & conf_api_sub_undeaf, CONF_API_SUB_MEMBER_TARGET, "undeaf", "<[member_id|all]|last>"}, + {"dtmf", (void_fn_t) & conf_api_sub_dtmf, CONF_API_SUB_MEMBER_TARGET, "dtmf", "<[member_id|all|last|non_moderator]> "}, + {"kick", (void_fn_t) & conf_api_sub_kick, CONF_API_SUB_MEMBER_TARGET, "kick", "<[member_id|all|last|non_moderator]> []"}, + {"hup", (void_fn_t) & conf_api_sub_hup, CONF_API_SUB_MEMBER_TARGET, "hup", "<[member_id|all|last|non_moderator]>"}, + {"mute", (void_fn_t) & conf_api_sub_mute, CONF_API_SUB_MEMBER_TARGET, "mute", "<[member_id|all]|last|non_moderator>"}, + {"unmute", (void_fn_t) & conf_api_sub_unmute, CONF_API_SUB_MEMBER_TARGET, "unmute", "<[member_id|all]|last|non_moderator>"}, + {"deaf", (void_fn_t) & conf_api_sub_deaf, CONF_API_SUB_MEMBER_TARGET, "deaf", "<[member_id|all]|last|non_moderator>"}, + {"undeaf", (void_fn_t) & conf_api_sub_undeaf, CONF_API_SUB_MEMBER_TARGET, "undeaf", "<[member_id|all]|last|non_moderator>"}, {"relate", (void_fn_t) & conf_api_sub_relate, CONF_API_SUB_ARGS_SPLIT, "relate", " [nospeak|nohear|clear]"}, {"lock", (void_fn_t) & conf_api_sub_lock, CONF_API_SUB_ARGS_SPLIT, "lock", ""}, {"unlock", (void_fn_t) & conf_api_sub_unlock, CONF_API_SUB_ARGS_SPLIT, "unlock", ""}, @@ -4974,6 +5218,7 @@ static api_command_t conf_api_sub_commands[] = { {"bgdial", (void_fn_t) & conf_api_sub_bgdial, CONF_API_SUB_ARGS_SPLIT, "bgdial", "/ "}, {"transfer", (void_fn_t) & conf_api_sub_transfer, CONF_API_SUB_ARGS_SPLIT, "transfer", " [...]"}, {"record", (void_fn_t) & conf_api_sub_record, CONF_API_SUB_ARGS_SPLIT, "record", ""}, + {"chkrecord", (void_fn_t) & conf_api_sub_check_record, CONF_API_SUB_ARGS_SPLIT, "chkrecord", ""}, {"norecord", (void_fn_t) & conf_api_sub_norecord, CONF_API_SUB_ARGS_SPLIT, "norecord", "<[filename|all]>"}, {"exit_sound", (void_fn_t) & conf_api_sub_exit_sound, CONF_API_SUB_ARGS_SPLIT, "exit_sound", "on|off|none|file "}, {"enter_sound", (void_fn_t) & conf_api_sub_enter_sound, CONF_API_SUB_ARGS_SPLIT, "enter_sound", "on|off|none|file "}, @@ -5008,22 +5253,24 @@ switch_status_t conf_api_dispatch(conference_obj_t *conference, switch_stream_ha } break; - /* member specific command that can be itteratted */ + /* member specific command that can be iterated */ case CONF_API_SUB_MEMBER_TARGET: { uint32_t id = 0; uint8_t all = 0; uint8_t last = 0; + uint8_t non_mod = 0; if (argv[argn + 1]) { if (!(id = atoi(argv[argn + 1]))) { all = strcasecmp(argv[argn + 1], "all") ? 0 : 1; + non_mod = strcasecmp(argv[argn + 1], "non_moderator") ? 0 : 1; last = strcasecmp(argv[argn + 1], "last") ? 0 : 1; } } - if (all) { - conference_member_itterator(conference, stream, (conf_api_member_cmd_t) conf_api_sub_commands[i].pfnapicmd, argv[argn + 2]); + if (all || non_mod) { + conference_member_itterator(conference, stream, non_mod, (conf_api_member_cmd_t) conf_api_sub_commands[i].pfnapicmd, argv[argn + 2]); } else if (last) { conference_member_t *member = NULL; conference_member_t *last_member = NULL; @@ -5133,10 +5380,6 @@ SWITCH_STANDARD_API(conf_api_main) conference_obj_t *conference = NULL; if ((conference = conference_find(argv[0]))) { - if (switch_thread_rwlock_tryrdlock(conference->rwlock) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Read Lock Fail\n"); - goto done; - } if (argc >= 2) { conf_api_dispatch(conference, stream, argc, argv, cmd, 1); } else { @@ -5177,7 +5420,7 @@ SWITCH_STANDARD_API(conf_api_main) } } - done: + switch_safe_free(lbuf); return status; @@ -5512,8 +5755,6 @@ static void set_mflags(const char *flags, member_flag_t *f) *f &= ~MFLAG_TALKING; } else if (!strcasecmp(argv[i], "deaf")) { *f &= ~MFLAG_CAN_HEAR; - } else if (!strcasecmp(argv[i], "waste")) { - *f |= MFLAG_WASTE_BANDWIDTH; } else if (!strcasecmp(argv[i], "mute-detect")) { *f |= MFLAG_MUTE_DETECT; } else if (!strcasecmp(argv[i], "dist-dtmf")) { @@ -5558,8 +5799,6 @@ static void set_cflags(const char *flags, uint32_t *f) *f |= CFLAG_WAIT_MOD; } else if (!strcasecmp(argv[i], "video-floor-only")) { *f |= CFLAG_VID_FLOOR; - } else if (!strcasecmp(argv[i], "waste-bandwidth")) { - *f |= CFLAG_WASTE_BANDWIDTH; } else if (!strcasecmp(argv[i], "video-bridge")) { *f |= CFLAG_VIDEO_BRIDGE; } @@ -5772,6 +6011,13 @@ static int setup_media(conference_member_t *member, conference_obj_t *conference } +#define validate_pin(buf, pin, mpin) \ + pin_valid = (!zstr(pin) && strcmp(buf, pin) == 0); \ + if (!pin_valid && !zstr(mpin) && strcmp(buf, mpin) == 0) { \ + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Moderator PIN found!\n"); \ + pin_valid = 1; \ + mpin_matched = 1; \ + } /* Application interface function that is called from the dialplan to join the channel to a conference */ SWITCH_STANDARD_APP(conference_function) { @@ -5791,10 +6037,12 @@ SWITCH_STANDARD_APP(conference_function) member_flag_t mflags = 0; switch_core_session_message_t msg = { 0 }; uint8_t rl = 0, isbr = 0; - char *dpin = NULL; + char *dpin = ""; + char *mdpin = ""; conf_xml_cfg_t xml_cfg = { 0 }; switch_event_t *params = NULL; int locked = 0; + int mpin_matched = 0; uint32_t *mid; if (!switch_channel_test_app_flag_key("conf_silent", channel, CONF_SILENT_DONE) && @@ -5859,10 +6107,10 @@ SWITCH_STANDARD_APP(conference_function) /* is there a conference pin ? */ if ((dpin = strchr(conf_name, '+'))) { *dpin++ = '\0'; - } + } else dpin = ""; /* is there profile specification ? */ - if ((profile_name = strchr(conf_name, '@'))) { + if ((profile_name = strrchr(conf_name, '@'))) { *profile_name++ = '\0'; } else { profile_name = "default"; @@ -5915,6 +6163,7 @@ SWITCH_STANDARD_APP(conference_function) } if ((conference = conference_find(conf_name))) { + switch_thread_rwlock_unlock(conference->rwlock); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Conference %s already exists!\n", conf_name); goto done; } @@ -6006,29 +6255,33 @@ SWITCH_STANDARD_APP(conference_function) /* Indicate the conference is dynamic */ switch_set_flag_locked(conference, CFLAG_DYNAMIC); + /* acquire a read lock on the thread so it can't leave without us */ + if (switch_thread_rwlock_tryrdlock(conference->rwlock) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Read Lock Fail\n"); + goto done; + } + + rl++; + /* Start the conference thread for this conference */ launch_conference_thread(conference); } else { /* setup user variable */ switch_channel_set_variable(channel, "conference_name", conference->name); + rl++; } - /* acquire a read lock on the thread so it can't leave without us */ - if (switch_thread_rwlock_tryrdlock(conference->rwlock) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Read Lock Fail\n"); - goto done; - } - rl++; - - if (!dpin && conference->pin) { + if (zstr(dpin) && conference->pin) { dpin = conference->pin; } - + if (zstr(mdpin) && conference->mpin) { + mdpin = conference->mpin; + } /* if this is not an outbound call, deal with conference pins */ - if (enforce_security && !zstr(dpin)) { + if (enforce_security && (!zstr(dpin) || !zstr(mdpin))) { char pin_buf[80] = ""; - int pin_retries = 3; /* XXX - this should be configurable - i'm too lazy to do it right now... */ + int pin_retries = conference->pin_retries; int pin_valid = 0; switch_status_t status = SWITCH_STATUS_SUCCESS; char *supplied_pin_value; @@ -6048,7 +6301,8 @@ SWITCH_STANDARD_APP(conference_function) while (*supplied_pin_value != 0 && *supplied_pin_value != ';') { pin_buf[i++] = *supplied_pin_value++; } - pin_valid = (strcmp(pin_buf, dpin) == 0); + + validate_pin(pin_buf, dpin, mdpin); memset(pin_buf, 0, sizeof(pin_buf)); } @@ -6061,6 +6315,7 @@ SWITCH_STANDARD_APP(conference_function) } while (!pin_valid && pin_retries && status == SWITCH_STATUS_SUCCESS) { + int maxpin = strlen(dpin) > strlen(mdpin) ? strlen(dpin) : strlen(mdpin); switch_status_t pstatus = SWITCH_STATUS_FALSE; /* be friendly */ @@ -6079,19 +6334,22 @@ SWITCH_STANDARD_APP(conference_function) } /* wait for them if neccessary */ - if (strlen(pin_buf) < strlen(dpin)) { + if (strlen(pin_buf) < maxpin) { char *buf = pin_buf + strlen(pin_buf); char term = '\0'; status = switch_ivr_collect_digits_count(session, buf, - sizeof(pin_buf) - strlen(pin_buf), strlen(dpin) - strlen(pin_buf), "#", &term, 10000, 0, 0); + sizeof(pin_buf) - strlen(pin_buf), maxpin - strlen(pin_buf), "#", &term, 10000, 0, 0); if (status == SWITCH_STATUS_TIMEOUT) { status = SWITCH_STATUS_SUCCESS; } } - pin_valid = (status == SWITCH_STATUS_SUCCESS && strcmp(pin_buf, dpin) == 0); + if (status == SWITCH_STATUS_SUCCESS) { + validate_pin(pin_buf, dpin, mdpin); + } + if (!pin_valid) { /* zero the collected pin */ memset(pin_buf, 0, sizeof(pin_buf)); @@ -6182,6 +6440,7 @@ SWITCH_STANDARD_APP(conference_function) switch_mutex_init(&member.flag_mutex, SWITCH_MUTEX_NESTED, member.pool); switch_mutex_init(&member.write_mutex, SWITCH_MUTEX_NESTED, member.pool); switch_mutex_init(&member.read_mutex, SWITCH_MUTEX_NESTED, member.pool); + switch_mutex_init(&member.fnode_mutex, SWITCH_MUTEX_NESTED, member.pool); switch_mutex_init(&member.audio_in_mutex, SWITCH_MUTEX_NESTED, member.pool); switch_mutex_init(&member.audio_out_mutex, SWITCH_MUTEX_NESTED, member.pool); switch_thread_rwlock_create(&member.rwlock, member.pool); @@ -6192,7 +6451,11 @@ SWITCH_STANDARD_APP(conference_function) mflags = conference->mflags; set_mflags(flags_str, &mflags); - switch_set_flag_locked((&member), MFLAG_RUNNING | mflags); + mflags |= MFLAG_RUNNING; + if (mpin_matched) { + mflags |= MFLAG_MOD; + } + switch_set_flag_locked((&member), mflags); if (mflags & MFLAG_MINTWO) { conference->min = 2; @@ -6259,17 +6522,19 @@ SWITCH_STANDARD_APP(conference_function) char *toplay = NULL; char *dfile = NULL; char *expanded = NULL; + char *src = member.kicked_sound ? member.kicked_sound : conference->kicked_sound; - if (!strncasecmp(conference->kicked_sound, "say:", 4)) { + + if (!strncasecmp(src, "say:", 4)) { if (conference->tts_engine && conference->tts_voice) { - switch_ivr_speak_text(session, conference->tts_engine, conference->tts_voice, conference->kicked_sound + 4, NULL); + switch_ivr_speak_text(session, conference->tts_engine, conference->tts_voice, src + 4, NULL); } } else { - if ((expanded = switch_channel_expand_variables(switch_core_session_get_channel(session), conference->kicked_sound)) != conference->kicked_sound) { + if ((expanded = switch_channel_expand_variables(switch_core_session_get_channel(session), src)) != src) { toplay = expanded; } else { expanded = NULL; - toplay = conference->kicked_sound; + toplay = src; } if (!switch_is_file_path(toplay) && conference->sound_prefix) { @@ -6332,19 +6597,33 @@ static void launch_conference_video_thread(conference_obj_t *conference) /* Create a video thread for the conference and launch it */ static void launch_conference_video_bridge_thread(conference_member_t *member_a, conference_member_t *member_b) { - switch_memory_pool_t *pool = member_a->conference->pool; - struct vid_helper *vh = switch_core_alloc(pool, 2 * sizeof *vh); - - vh[0].member_a = member_a; - vh[0].member_b = member_b; - - vh[1].member_a = member_b; - vh[1].member_b = member_a; - - launch_thread_detached(conference_video_bridge_thread_run, pool, &vh[0]); - launch_thread_detached(conference_video_bridge_thread_run, pool, &vh[1]); + conference_obj_t *conference = member_a->conference; + switch_memory_pool_t *pool = conference->pool; + int sanity = 10000; - member_a->conference->video_running = 1; + memset(conference->vh, 0, sizeof(conference->vh)); + + conference->vh[0].member_a = member_a; + conference->vh[0].member_b = member_b; + + conference->vh[1].member_a = member_b; + conference->vh[1].member_b = member_a; + + launch_thread_detached(conference_video_bridge_thread_run, pool, &conference->vh[0]); + launch_thread_detached(conference_video_bridge_thread_run, pool, &conference->vh[1]); + + while(!(conference->vh[0].up && conference->vh[1].up) && --sanity > 0) { + switch_cond_next(); + } + + if (conference->vh[0].up == 1 && conference->vh[1].up != 1) { + conference->vh[0].up = -1; + } + + if (conference->vh[1].up == 1 && conference->vh[0].up != 1) { + conference->vh[1].up = -1; + } + } static void launch_conference_record_thread(conference_obj_t *conference, char *path) @@ -6366,6 +6645,8 @@ static void launch_conference_record_thread(conference_obj_t *conference, char * return; } + conference->is_recording = 1; + rec->conference = conference; rec->path = switch_core_strdup(pool, path); rec->pool = pool; @@ -6432,6 +6713,7 @@ static switch_status_t chat_send(switch_event_t *message_event) switch_core_chat_send_args(proto, CONF_CHAT_PROTO, to, hint && strchr(hint, '/') ? hint : from, "", stream.data, NULL, NULL); switch_safe_free(stream.data); + switch_thread_rwlock_unlock(conference->rwlock); return SWITCH_STATUS_SUCCESS; } @@ -6448,6 +6730,12 @@ static conference_obj_t *conference_find(char *name) conference = NULL; } } + if (conference) { + if (switch_thread_rwlock_tryrdlock(conference->rwlock) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Read Lock Fail\n"); + conference = NULL; + } + } switch_mutex_unlock(globals.hash_mutex); return conference; @@ -6460,6 +6748,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c switch_xml_t xml_kvp; char *timer_name = NULL; char *domain = NULL; + char *name_domain = NULL; char *tts_engine = NULL; char *tts_voice = NULL; char *enter_sound = NULL; @@ -6476,6 +6765,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c char *is_unlocked_sound = NULL; char *kicked_sound = NULL; char *pin = NULL; + char *mpin = NULL; char *pin_sound = NULL; char *bad_pin_sound = NULL; char *energy_level = NULL; @@ -6483,6 +6773,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c char *caller_id_name = NULL; char *caller_id_number = NULL; char *caller_controls = NULL; + char *moderator_controls = NULL; char *member_flags = NULL; char *conference_flags = NULL; char *perpetual_sound = NULL; @@ -6492,9 +6783,13 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c char *maxmember_sound = NULL; uint32_t rate = 8000, interval = 20; int comfort_noise_level = 0; + int pin_retries = 3; + int ivr_dtmf_timeout = 500; + int ivr_input_timeout = 0; char *suppress_events = NULL; char *verbose_events = NULL; char *auto_record = NULL; + char *conference_log_dir = NULL; char *terminate_on_silence = NULL; char uuid_str[SWITCH_UUID_FORMATTED_LENGTH+1]; switch_uuid_t uuid; @@ -6624,10 +6919,19 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c member_flags = val; } else if (!strcasecmp(var, "conference-flags") && !zstr(val)) { conference_flags = val; + } else if (!strcasecmp(var, "cdr-log-dir") && !zstr(val)) { + conference_log_dir = val; } else if (!strcasecmp(var, "kicked-sound") && !zstr(val)) { kicked_sound = val; } else if (!strcasecmp(var, "pin") && !zstr(val)) { pin = val; + } else if (!strcasecmp(var, "moderator-pin") && !zstr(val)) { + mpin = val; + } else if (!strcasecmp(var, "pin-retries") && !zstr(val)) { + int tmp = atoi(val); + if (tmp >= 0) { + pin_retries = tmp; + } } else if (!strcasecmp(var, "pin-sound") && !zstr(val)) { pin_sound = val; } else if (!strcasecmp(var, "bad-pin-sound") && !zstr(val)) { @@ -6642,6 +6946,20 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c caller_id_number = val; } else if (!strcasecmp(var, "caller-controls") && !zstr(val)) { caller_controls = val; + } else if (!strcasecmp(var, "ivr-dtmf-timeout") && !zstr(val)) { + ivr_dtmf_timeout = atoi(val); + if (ivr_dtmf_timeout < 500) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "not very smart value for ivr-dtmf-timeout found (%d), defaulting to 500ms\n", ivr_dtmf_timeout); + ivr_dtmf_timeout = 500; + } + } else if (!strcasecmp(var, "ivr-input-timeout") && !zstr(val)) { + ivr_input_timeout = atoi(val); + if (ivr_input_timeout != 0 && ivr_input_timeout < 500) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "not very smart value for ivr-input-timeout found (%d), defaulting to 500ms\n", ivr_input_timeout); + ivr_input_timeout = 5000; + } + } else if (!strcasecmp(var, "moderator-controls") && !zstr(val)) { + moderator_controls = val; } else if (!strcasecmp(var, "comfort-noise") && !zstr(val)) { int tmp; tmp = atoi(val); @@ -6716,6 +7034,8 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c goto end; } + conference->start_time = switch_epoch_time_now(NULL); + /* initialize the conference object with settings from the specified profile */ conference->pool = pool; conference->profile_name = switch_core_strdup(conference->pool, cfg.profile ? switch_xml_attr_soft(cfg.profile, "name") : "none"); @@ -6730,10 +7050,28 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c } conference->comfort_noise_level = comfort_noise_level; + conference->pin_retries = pin_retries; conference->caller_id_name = switch_core_strdup(conference->pool, caller_id_name); conference->caller_id_number = switch_core_strdup(conference->pool, caller_id_number); conference->caller_controls = switch_core_strdup(conference->pool, caller_controls); + conference->moderator_controls = switch_core_strdup(conference->pool, moderator_controls); conference->run_time = switch_epoch_time_now(NULL); + + if (!zstr(conference_log_dir)) { + char *path; + + if (!strcmp(conference_log_dir, "auto")) { + path = switch_core_sprintf(conference->pool, "%s%sconference_cdr", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR); + } else if (!switch_is_file_path(conference_log_dir)) { + path = switch_core_sprintf(conference->pool, "%s%s%s", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, conference_log_dir); + } else { + path = switch_core_strdup(conference->pool, conference_log_dir); + } + + switch_dir_make_recursive(path, SWITCH_DEFAULT_DIR_PERMS, conference->pool); + conference->log_dir = path; + + } if (!zstr(perpetual_sound)) { @@ -6813,6 +7151,10 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c conference->pin = switch_core_strdup(conference->pool, pin); } + if (!zstr(mpin)) { + conference->mpin = switch_core_strdup(conference->pool, mpin); + } + if (!zstr(alone_sound)) { conference->alone_sound = switch_core_strdup(conference->pool, alone_sound); } @@ -6858,7 +7200,10 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c conference->announce_count = announce_count; conference->name = switch_core_strdup(conference->pool, name); - if (domain) { + + if ((name_domain = strchr(conference->name, '@'))) { + conference->domain = switch_core_strdup(conference->pool, name_domain); + } else if (domain) { conference->domain = switch_core_strdup(conference->pool, domain); } else { conference->domain = "cluecon.com"; @@ -6866,6 +7211,8 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c conference->rate = rate; conference->interval = interval; + conference->ivr_dtmf_timeout = ivr_dtmf_timeout; + conference->ivr_input_timeout = ivr_input_timeout; conference->eflags = 0xFFFFFFFF; if (!zstr(suppress_events)) { @@ -6910,32 +7257,77 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c return conference; } +static void conference_send_presence(conference_obj_t *conference) +{ + switch_event_t *event; + + if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", CONF_CHAT_PROTO); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", conference->name); + if (strchr(conference->name, '@')) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", conference->name); + } else { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", conference->name, conference->domain); + } + + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", conference->name); + + if (conference->count) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "force-status", "Active (%d caller%s)", conference->count, conference->count == 1 ? "" : "s"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_ROUTING"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", conference->count == 1 ? "early" : "confirmed"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-call-direction", conference->count == 1 ? "outbound" : "inbound"); + } else { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "force-status", "Inactive"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_HANGUP"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "terminated"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", "inbound"); + } + + + + switch_event_fire(&event); + } + +} + + static void pres_event_handler(switch_event_t *event) { char *to = switch_event_get_header(event, "to"); - char *dup_to = NULL, *conf_name, *e; + char *domain_name = NULL; + char *dup_to = NULL, *conf_name, *dup_conf_name = NULL; conference_obj_t *conference; - if (!to || strncasecmp(to, "conf+", 5)) { + if (!to || strncasecmp(to, "conf+", 5) || !strchr(to, '@')) { return; } if (!(dup_to = strdup(to))) { return; } + conf_name = dup_to + 5; - if ((e = strchr(conf_name, '@'))) { - *e = '\0'; + if ((domain_name = strchr(conf_name, '@'))) { + *domain_name++ = '\0'; } - if ((conference = conference_find(conf_name))) { + dup_conf_name = switch_mprintf("%q@%q", conf_name, domain_name); + + + if ((conference = conference_find(conf_name)) || (conference = conference_find(dup_conf_name))) { if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", CONF_CHAT_PROTO); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", conference->name); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", conference->name, conference->domain); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "Active (%d caller%s)", conference->count, conference->count == 1 ? "" : "s"); + + + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "force-status", "Active (%d caller%s)", conference->count, conference->count == 1 ? "" : "s"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++); @@ -6945,12 +7337,13 @@ static void pres_event_handler(switch_event_t *event) switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", conference->count == 1 ? "outbound" : "inbound"); switch_event_fire(&event); } + switch_thread_rwlock_unlock(conference->rwlock); } else if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", CONF_CHAT_PROTO); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", conf_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", to); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "Idle"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "idle"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "force-status", "Idle"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "unknown"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++); @@ -6962,6 +7355,7 @@ static void pres_event_handler(switch_event_t *event) } switch_safe_free(dup_to); + switch_safe_free(dup_conf_name); } static void send_presence(switch_event_types_t id) @@ -6990,8 +7384,8 @@ static void send_presence(switch_event_types_t id) switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", CONF_CHAT_PROTO); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", name); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", status ? status : "Available"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "idle"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "force-status", status ? status : "Available"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "unknown"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); switch_event_fire(&event); } diff --git a/src/mod/applications/mod_curl/Makefile b/src/mod/applications/mod_curl/Makefile index b276633355..6cae5a8595 100644 --- a/src/mod/applications/mod_curl/Makefile +++ b/src/mod/applications/mod_curl/Makefile @@ -1,6 +1,5 @@ json-c=json-c-0.9 BASE=../../../.. -WANT_CURL=yes JSON_DIR=$(switch_srcdir)/libs/$(json-c) JSON_BUILDDIR=$(switch_builddir)/libs/$(json-c) diff --git a/src/mod/applications/mod_curl/mod_curl.c b/src/mod/applications/mod_curl/mod_curl.c index adcfe453de..513e40fcd6 100644 --- a/src/mod/applications/mod_curl/mod_curl.c +++ b/src/mod/applications/mod_curl/mod_curl.c @@ -30,7 +30,7 @@ */ #include -#include +#include #include /* Prototypes */ @@ -57,7 +57,7 @@ struct http_data_obj { int err; long http_response_code; char *http_response; - struct curl_slist *headers; + switch_curl_slist_t *headers; }; typedef struct http_data_obj http_data_t; @@ -94,7 +94,7 @@ static size_t header_callback(void *ptr, size_t size, size_t nmemb, void *data) switch_copy_string(header, ptr, realsize); header[realsize] = '\0'; - http_data->headers = curl_slist_append(http_data->headers, header); + http_data->headers = switch_curl_slist_append(http_data->headers, header); return realsize; } @@ -102,7 +102,7 @@ static size_t header_callback(void *ptr, size_t size, size_t nmemb, void *data) static http_data_t *do_lookup_url(switch_memory_pool_t *pool, const char *url, const char *method, const char *data) { - CURL *curl_handle = NULL; + switch_CURL *curl_handle = NULL; long httpRes = 0; http_data_t *http_data = NULL; @@ -165,7 +165,7 @@ static char *print_json(switch_memory_pool_t *pool, http_data_t *http_data) struct json_object *top = NULL; struct json_object *headers = NULL; char *data = NULL; - struct curl_slist *header = http_data->headers; + switch_curl_slist_t *header = http_data->headers; top = json_object_new_object(); headers = json_object_new_array(); @@ -240,7 +240,7 @@ SWITCH_STANDARD_APP(curl_app_function) switch_bool_t do_headers = SWITCH_FALSE; switch_bool_t do_json = SWITCH_FALSE; http_data_t *http_data = NULL; - struct curl_slist *slist = NULL; + switch_curl_slist_t *slist = NULL; switch_stream_handle_t stream = { 0 }; int i = 0; @@ -308,7 +308,7 @@ SWITCH_STANDARD_APP(curl_app_function) done: switch_safe_free(stream.data); if (http_data && http_data->headers) { - curl_slist_free_all(http_data->headers); + switch_curl_slist_free_all(http_data->headers); } if (!session && pool) { switch_core_destroy_memory_pool(&pool); @@ -326,7 +326,7 @@ SWITCH_STANDARD_API(curl_function) char *postdata = NULL; switch_bool_t do_headers = SWITCH_FALSE; switch_bool_t do_json = SWITCH_FALSE; - struct curl_slist *slist = NULL; + switch_curl_slist_t *slist = NULL; http_data_t *http_data = NULL; int i = 0; @@ -391,7 +391,7 @@ SWITCH_STANDARD_API(curl_function) done: if (http_data && http_data->headers) { - curl_slist_free_all(http_data->headers); + switch_curl_slist_free_all(http_data->headers); } switch_safe_free(mydata); if (!session && pool) { @@ -426,7 +426,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_curl_load) SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_curl_shutdown) { /* Cleanup dynamically allocated config settings */ - return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index c088d81111..592bfb40de 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -30,6 +30,7 @@ * Bret McDanel * Luke Dashjr (OpenMethods, LLC) * Cesar Cepeda + * Chris Rienzo * * mod_dptools.c -- Raw Audio File Streaming Application Module * @@ -155,10 +156,13 @@ static switch_status_t digit_action_callback(switch_ivr_dmachine_match_t *match) switch_event_t *event; switch_status_t status; int exec = 0; + int api = 0; char *string = act->string; switch_channel_t *channel; switch_core_session_t *use_session = act->session; int x = 0; + char *flags = ""; + if (switch_ivr_dmachine_get_target(match->dmachine) == DIGIT_TARGET_PEER || act->target == DIGIT_TARGET_PEER || act->target == DIGIT_TARGET_BOTH) { if (switch_core_session_get_partner(act->session, &use_session) != SWITCH_STATUS_SUCCESS) { use_session = act->session; @@ -168,8 +172,9 @@ static switch_status_t digit_action_callback(switch_ivr_dmachine_match_t *match) top: x++; - string = act->string; + string = switch_core_session_strdup(use_session, act->string); exec = 0; + api = 0; channel = switch_core_session_get_channel(use_session); @@ -180,28 +185,69 @@ static switch_status_t digit_action_callback(switch_ivr_dmachine_match_t *match) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(act->session), SWITCH_LOG_DEBUG, "%s Digit match binding [%s][%s]\n", switch_channel_get_name(channel), act->string, act->value); - if (!strncasecmp(string, "exec:", 5)) { - string += 5; - exec = 1; + if (!strncasecmp(string, "exec", 4)) { + char *e; + + string += 4; + if (*string == ':') { + string++; + exec = 1; + } else if (*string == '[') { + flags = string; + if ((e = switch_find_end_paren(flags, '[', ']'))) { + if (e && *++e == ':') { + flags++; + *e++ = '\0'; + string = e; + exec = strchr(flags, 'i') ? 2 : 1; + } + } + } + } else if (!strncasecmp(string, "api:", 4)) { + string += 4; + api = 1; } switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, string, act->value); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "digits", match->match_digits); if (exec) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute", exec == 2 ? "non-blocking" : "blocking"); - } + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute", exec == 1 ? "non-blocking" : "blocking"); + } if ((status = switch_core_session_queue_event(use_session, &event)) != SWITCH_STATUS_SUCCESS) { switch_event_destroy(&event); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(use_session), SWITCH_LOG_WARNING, "%s event queue faiure.\n", + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(use_session), SWITCH_LOG_WARNING, "%s event queue failure.\n", switch_core_session_get_name(use_session)); } } if (exec) { - char *cmd = switch_core_session_sprintf(use_session, "%s::%s", string, act->value); - switch_ivr_broadcast_in_thread(use_session, cmd, SMF_ECHO_ALEG | (act->target == DIGIT_TARGET_BOTH ? 0 : SMF_HOLD_BLEG)); + if (exec == 2) { + switch_core_session_execute_application(use_session, string, act->value); + } else { + char *cmd = switch_core_session_sprintf(use_session, "%s::%s", string, act->value); + switch_media_flag_enum_t exec_flags = SMF_ECHO_ALEG; + + if (act->target != DIGIT_TARGET_BOTH && !strchr(flags, 'H')) { + exec_flags |= SMF_HOLD_BLEG; + } + + switch_ivr_broadcast_in_thread(use_session, cmd, exec_flags); + } + } else if (api) { + switch_stream_handle_t stream = { 0 }; + SWITCH_STANDARD_STREAM(stream); + switch_api_execute(string, act->value, NULL, &stream); + if (stream.data) { + switch_channel_set_variable(channel, "bind_digit_action_api_result", (char *)stream.data); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(act->session), SWITCH_LOG_DEBUG, "%s Digit match binding [%s][%s] api executed, %s\n", + switch_core_session_get_name(use_session), act->string, act->value, (char *)stream.data); + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(act->session), SWITCH_LOG_DEBUG, "%s Digit match binding [%s][%s] api executed\n", + switch_core_session_get_name(use_session), act->string, act->value); + } + switch_safe_free(stream.data); } @@ -247,6 +293,7 @@ SWITCH_STANDARD_APP(clear_digit_action_function) if ((dmachine = switch_core_session_get_dmachine(session, target))) { if (zstr(realm) || !strcasecmp(realm, "all")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Digit parser %s: Clearing all realms\n", switch_ivr_dmachine_get_name(dmachine)); switch_core_session_set_dmachine(session, NULL, target); switch_ivr_dmachine_destroy(&dmachine); } else { @@ -322,7 +369,7 @@ static void bind_to_session(switch_core_session_t *session, switch_ivr_dmachine_bind(dmachine, act->realm, act->input, 0, digit_action_callback, act); } -#define BIND_DIGIT_ACTION_USAGE ",,,[,][,]" +#define BIND_DIGIT_ACTION_USAGE ",,[,][,][,]" SWITCH_STANDARD_APP(bind_digit_action_function) { @@ -331,6 +378,7 @@ SWITCH_STANDARD_APP(bind_digit_action_function) char *argv[6] = { 0 }; switch_digit_action_target_t target, bind_target; char *target_str = "self", *bind_target_str = "self"; + char *value = ""; if (zstr(data)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Syntax Error, USAGE %s\n", BIND_DIGIT_ACTION_USAGE); @@ -340,12 +388,16 @@ SWITCH_STANDARD_APP(bind_digit_action_function) mydata = switch_core_session_strdup(session, data); argc = switch_separate_string(mydata, ',', argv, (sizeof(argv) / sizeof(argv[0]))); - - if (argc < 4 || zstr(argv[0]) || zstr(argv[1]) || zstr(argv[2]) || zstr(argv[3])) { + + if (argc < 3 || zstr(argv[0]) || zstr(argv[1]) || zstr(argv[2])) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Syntax Error, USAGE %s\n", BIND_DIGIT_ACTION_USAGE); return; } + if (argv[3]) { + value = argv[3]; + } + if (argv[4]) { target_str = argv[4]; } @@ -360,14 +412,14 @@ SWITCH_STANDARD_APP(bind_digit_action_function) switch(target) { case DIGIT_TARGET_PEER: - bind_to_session(session, argv[0], argv[1], argv[2], argv[3], DIGIT_TARGET_PEER, bind_target); + bind_to_session(session, argv[0], argv[1], argv[2], value, DIGIT_TARGET_PEER, bind_target); break; case DIGIT_TARGET_BOTH: - bind_to_session(session, argv[0], argv[1], argv[2], argv[3], DIGIT_TARGET_PEER, bind_target); - bind_to_session(session, argv[0], argv[1], argv[2], argv[3], DIGIT_TARGET_SELF, bind_target); + bind_to_session(session, argv[0], argv[1], argv[2], value, DIGIT_TARGET_PEER, bind_target); + bind_to_session(session, argv[0], argv[1], argv[2], value, DIGIT_TARGET_SELF, bind_target); break; default: - bind_to_session(session, argv[0], argv[1], argv[2], argv[3], DIGIT_TARGET_SELF, bind_target); + bind_to_session(session, argv[0], argv[1], argv[2], value, DIGIT_TARGET_SELF, bind_target); break; } } @@ -409,6 +461,51 @@ SWITCH_STANDARD_APP(detect_speech_function) } } +#define PLAY_AND_DETECT_SPEECH_SYNTAX " detect: {param1=val1,param2=val2}" +SWITCH_STANDARD_APP(play_and_detect_speech_function) +{ + switch_channel_t *channel = switch_core_session_get_channel(session); + char *argv[2]; + char *lbuf = NULL; + const char *response = "DONE"; + char *detect = NULL; + + switch_channel_set_variable(channel, "detect_speech_result", ""); + + if (zstr(data) || !(lbuf = switch_core_session_strdup(session, data)) || !(detect = strstr(lbuf, "detect:"))) { + /* bad input */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", PLAY_AND_DETECT_SPEECH_SYNTAX); + response = "USAGE ERROR"; + goto done; + } + + /* split input at "detect:" */ + detect[0] = '\0'; + detect += 7; + if (zstr(detect)) { + /* bad input */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", PLAY_AND_DETECT_SPEECH_SYNTAX); + response = "USAGE ERROR"; + goto done; + } + + /* need to have at 2 parameters for detect */ + if (switch_separate_string(detect, ' ', argv, (sizeof(argv) / sizeof(argv[0]))) == 2) { + char *file = lbuf; + char *engine = argv[0]; + char *grammar = argv[1]; + char *result = NULL; + switch_ivr_play_and_detect_speech(session, file, engine, grammar, &result); + switch_channel_set_variable(channel, "detect_speech_result", result); + } else { + /* bad input */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", PLAY_AND_DETECT_SPEECH_SYNTAX); + response = "USAGE ERROR"; + } + +done: + switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, response); +} #define SCHED_HEARTBEAT_SYNTAX "[0|]" SWITCH_STANDARD_APP(sched_heartbeat_function) @@ -1080,6 +1177,19 @@ SWITCH_STANDARD_APP(redirect_function) switch_core_session_receive_message(session, &msg); } +SWITCH_STANDARD_APP(send_info_function) +{ + switch_core_session_message_t msg = { 0 }; + + /* Tell the channel to send info */ + msg.from = __FILE__; + msg.string_arg = data; + msg.message_id = SWITCH_MESSAGE_INDICATE_INFO; + msg.string_array_arg[2] = data; + + switch_core_session_receive_message(session, &msg); +} + SWITCH_STANDARD_APP(jitterbuffer_function) { switch_core_session_message_t msg = { 0 }; @@ -1561,7 +1671,7 @@ SWITCH_STANDARD_API(chat_api_function) if (!zstr(cmd) && (lbuf = strdup(cmd)) && (argc = switch_separate_string(lbuf, '|', argv, (sizeof(argv) / sizeof(argv[0])))) >= 4) { - if (switch_core_chat_send_args(argv[0], "dp", argv[1], argv[2], "", argv[3], !zstr(argv[4]) ? argv[4] : NULL, "") == SWITCH_STATUS_SUCCESS) { + if (switch_core_chat_send_args(argv[0], "global", argv[1], argv[2], "", argv[3], !zstr(argv[4]) ? argv[4] : NULL, "") == SWITCH_STATUS_SUCCESS) { stream->write_function(stream, "Sent"); } else { stream->write_function(stream, "Error! Message Not Sent"); @@ -3133,7 +3243,7 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session, switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause) { - switch_xml_t xml = NULL, x_user = NULL, x_param, x_params; + switch_xml_t x_user = NULL, x_param, x_params; char *user = NULL, *domain = NULL, *dup_domain = NULL; const char *dest = NULL; switch_call_cause_t cause = SWITCH_CAUSE_NONE; @@ -3298,8 +3408,8 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session, switch_safe_free(d_dest); } } - - if (new_channel && xml) { + + if (new_channel && x_user) { if ((x_params = switch_xml_child(x_user, "variables"))) { for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) { const char *pvar = switch_xml_attr(x_param, "name"); @@ -3311,7 +3421,9 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session, done: - switch_xml_free(xml); + if (x_user) { + switch_xml_free(x_user); + } if (params) { switch_event_destroy(¶ms); @@ -3729,8 +3841,8 @@ static int next_file(switch_file_handle_t *handle) } handle->samples = context->fh.samples; - handle->samplerate = context->fh.samplerate; - handle->channels = context->fh.channels; + //handle->samplerate = context->fh.samplerate; + //handle->channels = context->fh.channels; handle->format = context->fh.format; handle->sections = context->fh.sections; handle->seekable = context->fh.seekable; @@ -3970,9 +4082,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SWITCH_ADD_APP(app_interface, "remove_bugs", "Remove media bugs", "Remove all media bugs from a channel.", remove_bugs_function, "", SAF_NONE); SWITCH_ADD_APP(app_interface, "break", "Break", "Set the break flag.", break_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "detect_speech", "Detect speech", "Detect speech on a channel.", detect_speech_function, DETECT_SPEECH_SYNTAX, SAF_NONE); + SWITCH_ADD_APP(app_interface, "play_and_detect_speech", "Play and do speech recognition", "Play and do speech recognition", play_and_detect_speech_function, PLAY_AND_DETECT_SPEECH_SYNTAX, SAF_NONE); SWITCH_ADD_APP(app_interface, "ivr", "Run an ivr menu", "Run an ivr menu.", ivr_application_function, "", SAF_NONE); SWITCH_ADD_APP(app_interface, "redirect", "Send session redirect", "Send a redirect message to a session.", redirect_function, "", SAF_SUPPORT_NOMEDIA); + SWITCH_ADD_APP(app_interface, "send_info", "Send info", "Send info", send_info_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "jitterbuffer", "Send session jitterbuffer", "Send a jitterbuffer message to a session.", jitterbuffer_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "send_display", "Send session a new display", "Send session a new display.", display_function, "", @@ -3985,7 +4099,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "send_dtmf", "Send dtmf to be sent", "Send dtmf to be sent from a session", send_dtmf_function, "", SAF_SUPPORT_NOMEDIA); - SWITCH_ADD_APP(app_interface, "sched_cencel", "cancel scheduled tasks", "cancel scheduled tasks", sched_cancel_function, "[group]", + SWITCH_ADD_APP(app_interface, "sched_cancel", "cancel scheduled tasks", "cancel scheduled tasks", sched_cancel_function, "[group]", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "sched_hangup", SCHED_HANGUP_DESCR, SCHED_HANGUP_DESCR, sched_hangup_function, "[+] + + {d331904d-a00a-4694-a5a3-fcff64ab5dbe} + + + {b4b62169-5ad4-4559-8707-3d933ac5db39} + {202d7a4e-760d-4d0e-afa1-d7459ced30ff} false diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index 1a7dd221ef..7de70de36e 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -40,6 +40,7 @@ #define DL_EVENT_LOGIN_FAILURE "dingaling::login_failure" #define DL_EVENT_CONNECTED "dingaling::connected" #define MDL_CHAT_PROTO "jingle" +#define MDL_CHAT_FROM_GUESS "auto_from" SWITCH_MODULE_LOAD_FUNCTION(mod_dingaling_load); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_dingaling_shutdown); @@ -495,18 +496,24 @@ static switch_status_t chat_send(switch_event_t *message_event) mdl_profile_t *profile = NULL; const char *proto; const char *from; + const char *from_full; + const char *to_full; const char *to; const char *body; const char *hint; + const char *profile_name; proto = switch_event_get_header(message_event, "proto"); from = switch_event_get_header(message_event, "from"); + from_full = switch_event_get_header(message_event, "from_full"); + to_full = switch_event_get_header(message_event, "to_full"); to = switch_event_get_header(message_event, "to"); body = switch_event_get_body(message_event); hint = switch_event_get_header(message_event, "hint"); + profile_name = switch_event_get_header(message_event, "ldl_profile"); switch_assert(proto != NULL); - + if (from && (f_user = strdup(from))) { if ((f_host = strchr(f_user, '@'))) { *f_host++ = '\0'; @@ -516,12 +523,18 @@ static switch_status_t chat_send(switch_event_t *message_event) } } - if (to && (user = strdup(to))) { + if ((profile_name && (profile = switch_core_hash_find(globals.profile_hash, profile_name)))) { + from = from_full; + to = to_full; + + ldl_handle_send_msg(profile->handle, (char *) from, (char *) to, NULL, switch_str_nil(body)); + } else if (to && (user = strdup(to))) { if ((host = strchr(user, '@'))) { *host++ = '\0'; } - if (f_host && (profile = switch_core_hash_find(globals.profile_hash, f_host))) { + if (f_host && ((profile_name && (profile = switch_core_hash_find(globals.profile_hash, profile_name))) + || (profile = switch_core_hash_find(globals.profile_hash, f_host)))) { if (!strcmp(proto, MDL_CHAT_PROTO)) { from = hint; @@ -538,7 +551,12 @@ static switch_status_t chat_send(switch_event_t *message_event) *p = '\0'; } } - ldl_handle_send_msg(profile->handle, (char *) from, (char *) to, NULL, switch_str_nil(body)); + if (!(profile->user_flags & LDL_FLAG_COMPONENT) && !strcmp(f_user, MDL_CHAT_FROM_GUESS)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Using auto_from jid address for profile %s\n", profile->name); + ldl_handle_send_msg(profile->handle, NULL, (char *) to, NULL, switch_str_nil(body)); + } else { + ldl_handle_send_msg(profile->handle, (char *) from, (char *) to, NULL, switch_str_nil(body)); + } switch_safe_free(ffrom); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Profile %s\n", f_host ? f_host : "NULL"); @@ -1585,8 +1603,10 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s channel_answer_channel(session); break; case SWITCH_MESSAGE_INDICATE_BRIDGE: + rtp_flush_read_buffer(tech_pvt->rtp_session, SWITCH_RTP_FLUSH_STICK); break; case SWITCH_MESSAGE_INDICATE_UNBRIDGE: + rtp_flush_read_buffer(tech_pvt->rtp_session, SWITCH_RTP_FLUSH_UNSTICK); break; default: break; @@ -2931,6 +2951,8 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", subject); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "text/plain"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", hint); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_full", hint); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "ldl_profile", profile->name); if (msg) { switch_event_add_body(event, "%s", msg); @@ -2941,12 +2963,14 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi switch_safe_free(from_user); - if (strcasecmp(proto, MDL_CHAT_PROTO)) { /* yes no ! on purpose */ - switch_core_chat_send(proto, event); + if (!zstr(msg)) { + if (strcasecmp(proto, MDL_CHAT_PROTO)) { /* yes no ! on purpose */ + switch_core_chat_send(proto, event); + } + + switch_core_chat_send("GLOBAL", event); } - switch_core_chat_send("GLOBAL", event); - switch_event_destroy(&event); switch_safe_free(pproto); diff --git a/src/mod/endpoints/mod_gsmopen/README b/src/mod/endpoints/mod_gsmopen/README index 18659c1be4..0335ad1deb 100644 --- a/src/mod/endpoints/mod_gsmopen/README +++ b/src/mod/endpoints/mod_gsmopen/README @@ -31,5 +31,6 @@ Enjoy -giovanni + < gmaruzz at gmail dot com > diff --git a/src/mod/endpoints/mod_h323/changes.txt b/src/mod/endpoints/mod_h323/changes.txt index 80d9119e4d..93a75e8b0f 100644 --- a/src/mod/endpoints/mod_h323/changes.txt +++ b/src/mod/endpoints/mod_h323/changes.txt @@ -1,3 +1,5 @@ +fix stale calls then fax send/recv in some circumstance +remove SWITCH_RTP_FLAG_AUTO_CNG - works incorrectly. moves the switch_rtp_request_port() call from the contructor to FSH323Connection::CreateRealTimeLogicalChannel() - fix rtp port leak. tnx to Peter Olsson. fix log printing diff --git a/src/mod/endpoints/mod_h323/mod_h323.cpp b/src/mod/endpoints/mod_h323/mod_h323.cpp index 26323ddaea..e7199e0dee 100644 --- a/src/mod/endpoints/mod_h323/mod_h323.cpp +++ b/src/mod/endpoints/mod_h323/mod_h323.cpp @@ -33,7 +33,7 @@ * * mod_h323.cpp -- H323 endpoint * - * Version 0.0.57 + * Version 0.0.58 */ //#define DEBUG_RTP_PACKETS @@ -201,10 +201,14 @@ SWITCH_END_EXTERN_C void h_timer(unsigned sec) { +#ifdef WIN32 + switch_sleep(sec * 1000000); +#else timeval timeout; timeout.tv_sec = sec; timeout.tv_usec = 0; select(0, NULL, NULL, NULL, &timeout); +#endif } @@ -1098,7 +1102,7 @@ bool FSH323Connection::OnSendReleaseComplete(H323SignalPDU & pdu) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"======>FSH323Connection::OnSendReleaseComplete cause = %u\n",(switch_call_cause_t)pdu.GetQ931().GetCause()); - switch_channel_hangup(m_fsChannel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + switch_channel_hangup(m_fsChannel, (switch_call_cause_t) pdu.GetQ931().GetCause()); return H323Connection::OnSendReleaseComplete(pdu); } @@ -1333,7 +1337,19 @@ void FSH323Connection::OnModeChanged(const H245_ModeDescription & newMode) const char *uuid = switch_channel_get_variable(m_fsChannel, SWITCH_SIGNAL_BOND_VARIABLE); if (uuid != NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"uuid:%s\n",uuid); - switch_channel_set_private(switch_core_session_get_channel(switch_core_session_locate(switch_channel_get_variable(m_fsChannel, SWITCH_SIGNAL_BOND_VARIABLE))), "t38_options", t38_options); + + switch_core_session_t *session = switch_core_session_locate(switch_channel_get_variable(m_fsChannel, SWITCH_SIGNAL_BOND_VARIABLE)); + if (session) { + switch_channel_t * channel = switch_core_session_get_channel(session); + if (channel) { + switch_channel_set_private(channel, "t38_options", t38_options); + }else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no channel?\n"); + } + switch_core_session_rwunlock(session); + }else{ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no session\n"); + } switch_core_session_message_t msg = { 0 }; @@ -1887,6 +1903,7 @@ FSH323_ExternalRTPChannel::FSH323_ExternalRTPChannel(FSH323Connection& connectio , m_capability(&capability) , m_RTPlocalPort(dataPort) , m_sessionID(sessionID) + , m_rtp_resetting(0) { m_RTPlocalIP = (const char *)ip.AsString(); SetExternalAddress(H323TransportAddress(ip, dataPort), H323TransportAddress(ip, dataPort+1)); @@ -2046,9 +2063,6 @@ PBoolean FSH323_ExternalRTPChannel::Start() , GetMainTypes[m_capability->GetMainType()],(const char*)(m_capability->GetFormatName()),this); } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"%s Unsupported ptime of %u on %s %s codec %s for connection [%p]\n",switch_channel_get_name(m_fsChannel),((GetDirection() == IsReceiver)? " read" : " write") - , GetMainTypes[m_capability->GetMainType()],(const char*)(m_capability->GetFormatName()),this); - if (GetDirection() == IsReceiver) { //m_readFrame.rate = tech_pvt->read_codec.implementation->actual_samples_per_second; @@ -2113,7 +2127,7 @@ PBoolean FSH323_ExternalRTPChannel::Start() bool ch_port = false; if (tech_pvt->rtp_session != NULL){ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"------------------->old remot port = %d new remote port = %d\n",switch_rtp_get_remote_port(tech_pvt->rtp_session),m_RTPremotePort); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"------------------->old remote port = %d new remote port = %d\n",switch_rtp_get_remote_port(tech_pvt->rtp_session),m_RTPremotePort); if ((switch_rtp_get_remote_port(tech_pvt->rtp_session) != m_RTPremotePort) && (GetDirection() != IsReceiver) && (m_conn->m_rtp_resetting == 1)){ ch_port = true; m_conn->m_startRTP = false; @@ -2131,7 +2145,7 @@ PBoolean FSH323_ExternalRTPChannel::Start() } if ((!m_conn->m_startRTP)) { - flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_DATAWAIT|SWITCH_RTP_FLAG_AUTO_CNG|SWITCH_RTP_FLAG_RAW_WRITE); + flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_DATAWAIT|SWITCH_RTP_FLAG_RAW_WRITE); if (mod_h323_globals.use_rtp_timer) { flags |= SWITCH_RTP_FLAG_USE_TIMER; @@ -2401,9 +2415,13 @@ static switch_status_t on_hangup(switch_core_session_t *session) switch_mutex_lock(tech_pvt->h323_mutex); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"------------->h323_mutex_unlock\n"); switch_mutex_unlock(tech_pvt->h323_mutex); + while (tech_pvt->active_connection){ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Wait clear h323 connection\n"); h_timer(1); } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "H323 connection was cleared successfully\n"); + return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/endpoints/mod_h323/mod_h323.h b/src/mod/endpoints/mod_h323/mod_h323.h index 3a0d7aa235..3e046d1093 100644 --- a/src/mod/endpoints/mod_h323/mod_h323.h +++ b/src/mod/endpoints/mod_h323/mod_h323.h @@ -32,7 +32,7 @@ * * mod_h323.h -- H323 endpoint * - * Version 0.0.57 + * Version 0.0.58 */ #if defined(__GNUC__) && defined(HAVE_VISIBILITY) diff --git a/src/mod/endpoints/mod_khomp/src/khomp_pvt_kxe1.cpp b/src/mod/endpoints/mod_khomp/src/khomp_pvt_kxe1.cpp index aaacd4ecba..b5f68132e6 100644 --- a/src/mod/endpoints/mod_khomp/src/khomp_pvt_kxe1.cpp +++ b/src/mod/endpoints/mod_khomp/src/khomp_pvt_kxe1.cpp @@ -1399,6 +1399,8 @@ int BoardE1::KhompPvtR2::callFailFromCause(int cause) case SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET: case SWITCH_CAUSE_NO_ROUTE_DESTINATION: case SWITCH_CAUSE_INVALID_NUMBER_FORMAT: + case SWITCH_CAUSE_INVALID_GATEWAY: + case SWITCH_CAUSE_INVALID_URL: case SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED: case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION: @@ -1430,7 +1432,9 @@ int BoardE1::KhompPvtR2::callFailFromCause(int cause) case SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL: case SWITCH_CAUSE_CHANNEL_UNACCEPTABLE: case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER: + case SWITCH_CAUSE_INVALID_PROFILE: case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER: + case SWITCH_CAUSE_GATEWAY_DOWN: case SWITCH_CAUSE_FACILITY_REJECTED: case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED: case SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED: @@ -1448,6 +1452,8 @@ int BoardE1::KhompPvtR2::callFailFromCause(int cause) case SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET: case SWITCH_CAUSE_NO_ROUTE_DESTINATION: case SWITCH_CAUSE_INVALID_NUMBER_FORMAT: + case SWITCH_CAUSE_INVALID_GATEWAY: + case SWITCH_CAUSE_INVALID_URL: case SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED: case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION: @@ -1480,6 +1486,7 @@ int BoardE1::KhompPvtR2::callFailFromCause(int cause) case SWITCH_CAUSE_CHANNEL_UNACCEPTABLE: case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER: case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER: + case SWITCH_CAUSE_GATEWAY_DOWN: case SWITCH_CAUSE_FACILITY_REJECTED: case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED: case SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED: @@ -1497,6 +1504,8 @@ int BoardE1::KhompPvtR2::callFailFromCause(int cause) case SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET: case SWITCH_CAUSE_NO_ROUTE_DESTINATION: case SWITCH_CAUSE_INVALID_NUMBER_FORMAT: + case SWITCH_CAUSE_INVALID_GATEWAY: + case SWITCH_CAUSE_INVALID_URL: case SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED: case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION: @@ -1529,6 +1538,7 @@ int BoardE1::KhompPvtR2::callFailFromCause(int cause) case SWITCH_CAUSE_CHANNEL_UNACCEPTABLE: case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER: case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER: + case SWITCH_CAUSE_GATEWAY_DOWN: case SWITCH_CAUSE_FACILITY_REJECTED: case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED: case SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED: @@ -1553,6 +1563,8 @@ int BoardE1::KhompPvtR2::callFailFromCause(int cause) case SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET: case SWITCH_CAUSE_NO_ROUTE_DESTINATION: case SWITCH_CAUSE_INVALID_NUMBER_FORMAT: + case SWITCH_CAUSE_INVALID_GATEWAY: + case SWITCH_CAUSE_INVALID_URL: case SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED: case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION: @@ -1585,6 +1597,7 @@ int BoardE1::KhompPvtR2::callFailFromCause(int cause) case SWITCH_CAUSE_CHANNEL_UNACCEPTABLE: case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER: case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER: + case SWITCH_CAUSE_GATEWAY_DOWN: case SWITCH_CAUSE_FACILITY_REJECTED: case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED: case SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED: @@ -1622,6 +1635,8 @@ int BoardE1::KhompPvtR2::callFailFromCause(int cause) case SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET: case SWITCH_CAUSE_NO_ROUTE_DESTINATION: case SWITCH_CAUSE_INVALID_NUMBER_FORMAT: + case SWITCH_CAUSE_INVALID_GATEWAY: + case SWITCH_CAUSE_INVALID_URL: case SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED: case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION: @@ -1629,6 +1644,7 @@ int BoardE1::KhompPvtR2::callFailFromCause(int cause) case SWITCH_CAUSE_CHANNEL_UNACCEPTABLE: case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER: case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER: + case SWITCH_CAUSE_GATEWAY_DOWN: case SWITCH_CAUSE_FACILITY_REJECTED: case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED: case SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED: diff --git a/src/mod/endpoints/mod_loopback/mod_loopback.c b/src/mod/endpoints/mod_loopback/mod_loopback.c index 17f0b91e7a..3ec843e187 100644 --- a/src/mod/endpoints/mod_loopback/mod_loopback.c +++ b/src/mod/endpoints/mod_loopback/mod_loopback.c @@ -84,6 +84,7 @@ struct private_object { char *other_uuid; switch_queue_t *frame_queue; int64_t packet_count; + int first_cng; }; typedef struct private_object private_t; @@ -115,6 +116,7 @@ static void clear_queue(private_t *tech_pvt) switch_frame_t *frame = (switch_frame_t *) pop; switch_frame_free(&frame); } + } static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *session, switch_codec_t *codec) @@ -174,7 +176,7 @@ static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *ses tech_pvt->cng_frame.datalen = 2; tech_pvt->bowout_frame_count = (tech_pvt->read_codec.implementation->actual_samples_per_second / - tech_pvt->read_codec.implementation->samples_per_packet) * 3; + tech_pvt->read_codec.implementation->samples_per_packet) * 2; switch_core_session_set_read_codec(session, &tech_pvt->read_codec); switch_core_session_set_write_codec(session, &tech_pvt->write_codec); @@ -594,11 +596,16 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch *frame = tech_pvt->write_frame; tech_pvt->packet_count++; switch_clear_flag(tech_pvt->write_frame, SFF_CNG); + tech_pvt->first_cng = 0; } else { *frame = &tech_pvt->cng_frame; tech_pvt->cng_frame.codec = &tech_pvt->read_codec; tech_pvt->cng_frame.datalen = tech_pvt->read_codec.implementation->decoded_bytes_per_packet; switch_set_flag((&tech_pvt->cng_frame), SFF_CNG); + if (!tech_pvt->first_cng) { + switch_yield(tech_pvt->read_codec.implementation->samples_per_packet); + tech_pvt->first_cng = 1; + } } @@ -644,33 +651,56 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc switch_channel_test_flag(tech_pvt->channel, CF_BRIDGED) && switch_channel_test_flag(tech_pvt->other_channel, CF_BRIDGED) && switch_channel_test_flag(tech_pvt->channel, CF_ANSWERED) && - switch_channel_test_flag(tech_pvt->other_channel, CF_ANSWERED) && !--tech_pvt->bowout_frame_count <= 0) { + switch_channel_test_flag(tech_pvt->other_channel, CF_ANSWERED) && --tech_pvt->bowout_frame_count <= 0) { const char *a_uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE); const char *b_uuid = switch_channel_get_variable(tech_pvt->other_channel, SWITCH_SIGNAL_BOND_VARIABLE); const char *vetoa, *vetob; - switch_set_flag_locked(tech_pvt, TFLAG_BOWOUT); - switch_set_flag_locked(tech_pvt->other_tech_pvt, TFLAG_BOWOUT); vetoa = switch_channel_get_variable(tech_pvt->channel, "loopback_bowout"); vetob = switch_channel_get_variable(tech_pvt->other_tech_pvt->channel, "loopback_bowout"); if ((!vetoa || switch_true(vetoa)) && (!vetob || switch_true(vetob))) { - switch_clear_flag_locked(tech_pvt, TFLAG_WRITE); - switch_clear_flag_locked(tech_pvt->other_tech_pvt, TFLAG_WRITE); + switch_core_session_t *br_a, *br_b; + switch_channel_t *ch_a = NULL, *ch_b = NULL; + int good_to_go = 0; + + if ((br_a = switch_core_session_locate(a_uuid))) { + ch_a = switch_core_session_get_channel(br_a); + } - switch_set_flag_locked(tech_pvt, TFLAG_BOWOUT_USED); - switch_set_flag_locked(tech_pvt->other_tech_pvt, TFLAG_BOWOUT_USED); + if ((br_b = switch_core_session_locate(b_uuid))) { + ch_b = switch_core_session_get_channel(br_b); + } + + if (ch_a && ch_b && switch_channel_test_flag(ch_a, CF_BRIDGED) && switch_channel_test_flag(ch_b, CF_BRIDGED)) { + switch_set_flag_locked(tech_pvt, TFLAG_BOWOUT); + switch_set_flag_locked(tech_pvt->other_tech_pvt, TFLAG_BOWOUT); - if (a_uuid && b_uuid) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, - "%s detected bridge on both ends, attempting direct connection.\n", switch_channel_get_name(channel)); + switch_clear_flag_locked(tech_pvt, TFLAG_WRITE); + switch_clear_flag_locked(tech_pvt->other_tech_pvt, TFLAG_WRITE); - /* channel_masquerade eat your heart out....... */ - switch_ivr_uuid_bridge(a_uuid, b_uuid); - switch_mutex_unlock(tech_pvt->mutex); + switch_set_flag_locked(tech_pvt, TFLAG_BOWOUT_USED); + switch_set_flag_locked(tech_pvt->other_tech_pvt, TFLAG_BOWOUT_USED); + + if (a_uuid && b_uuid) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, + "%s detected bridge on both ends, attempting direct connection.\n", switch_channel_get_name(channel)); + + /* channel_masquerade eat your heart out....... */ + switch_ivr_uuid_bridge(a_uuid, b_uuid); + good_to_go = 1; + switch_mutex_unlock(tech_pvt->mutex); + } + } + + if (br_a) switch_core_session_rwunlock(br_a); + if (br_b) switch_core_session_rwunlock(br_b); + + if (good_to_go) { return SWITCH_STATUS_SUCCESS; } + } } diff --git a/src/mod/endpoints/mod_portaudio/pablio.c b/src/mod/endpoints/mod_portaudio/pablio.c index 6423dc762d..34a52df335 100644 --- a/src/mod/endpoints/mod_portaudio/pablio.c +++ b/src/mod/endpoints/mod_portaudio/pablio.c @@ -93,7 +93,7 @@ static int iblockingIOCallback(const void *inputBuffer, void *outputBuffer, } if (PaUtil_WriteRingBuffer(&data->inFIFOs[c], chanSamples, numBytes) != numBytes) { PaUtil_FlushRingBuffer(&data->inFIFOs[c]); - PaUtil_WriteRingBuffer(&data->inFIFOs[c], inputBuffer, numBytes); + PaUtil_WriteRingBuffer(&data->inFIFOs[c], chanSamples, numBytes); } } } diff --git a/src/mod/endpoints/mod_rtmp/mod_rtmp.c b/src/mod/endpoints/mod_rtmp/mod_rtmp.c index 45daf7bfea..9d2039e37e 100644 --- a/src/mod/endpoints/mod_rtmp/mod_rtmp.c +++ b/src/mod/endpoints/mod_rtmp/mod_rtmp.c @@ -266,10 +266,6 @@ switch_status_t rtmp_on_hangup(switch_core_session_t *session) rtmp_notify_call_state(session); rtmp_send_onhangup(session); - switch_mutex_lock(tech_pvt->rtmp_session->count_mutex); - tech_pvt->rtmp_session->active_sessions--; - switch_mutex_unlock(tech_pvt->rtmp_session->count_mutex); - switch_core_hash_delete_wrlock(tech_pvt->rtmp_session->session_hash, switch_core_session_get_uuid(session), tech_pvt->rtmp_session->session_rwlock); switch_mutex_lock(tech_pvt->rtmp_session->profile->mutex); @@ -279,6 +275,10 @@ switch_status_t rtmp_on_hangup(switch_core_session_t *session) } switch_mutex_unlock(tech_pvt->rtmp_session->profile->mutex); + switch_mutex_lock(tech_pvt->rtmp_session->count_mutex); + tech_pvt->rtmp_session->active_sessions--; + switch_mutex_unlock(tech_pvt->rtmp_session->count_mutex); + #ifndef RTMP_DONT_HOLD if (switch_channel_test_flag(channel, CF_HOLD)) { switch_channel_mark_hold(channel, SWITCH_FALSE); @@ -407,6 +407,7 @@ switch_status_t rtmp_read_frame(switch_core_session_t *session, switch_frame_t * return SWITCH_STATUS_SUCCESS; cng: + data = (switch_byte_t *) tech_pvt->read_frame.data; data[0] = 65; data[1] = 0; @@ -414,7 +415,7 @@ cng: tech_pvt->read_frame.flags = SFF_CNG; tech_pvt->read_frame.codec = &tech_pvt->read_codec; - switch_core_timer_sync(&tech_pvt->timer); + //switch_core_timer_sync(&tech_pvt->timer); *frame = &tech_pvt->read_frame; @@ -515,13 +516,13 @@ switch_status_t rtmp_receive_message(switch_core_session_t *session, switch_core const char *name = msg->string_array_arg[0], *number = msg->string_array_arg[1]; char *arg = NULL; char *argv[2] = { 0 }; - int argc; + //int argc; if (zstr(name) && !zstr(msg->string_arg)) { arg = strdup(msg->string_arg); switch_assert(arg); - argc = switch_separate_string(arg, '|', argv, (sizeof(argv) / sizeof(argv[0]))); + switch_separate_string(arg, '|', argv, (sizeof(argv) / sizeof(argv[0]))); name = argv[0]; number = argv[1]; diff --git a/src/mod/endpoints/mod_rtmp/mod_rtmp.h b/src/mod/endpoints/mod_rtmp/mod_rtmp.h index aec0430b56..388afeacb5 100644 --- a/src/mod/endpoints/mod_rtmp/mod_rtmp.h +++ b/src/mod/endpoints/mod_rtmp/mod_rtmp.h @@ -520,6 +520,7 @@ struct rtmp_private { const char *auth; uint16_t maxlen; + int over_size; }; struct rtmp_reg; diff --git a/src/mod/endpoints/mod_rtmp/rtmp.c b/src/mod/endpoints/mod_rtmp/rtmp.c index 10a48b3748..701487020e 100644 --- a/src/mod/endpoints/mod_rtmp/rtmp.c +++ b/src/mod/endpoints/mod_rtmp/rtmp.c @@ -23,6 +23,7 @@ * Contributor(s): * * Mathieu Rene + * Joao Mesquita * * rtmp.c -- RTMP Protocol Handler * @@ -104,7 +105,9 @@ void rtmp_handle_control(rtmp_session_t *rsession, int amfnumber) void rtmp_handle_invoke(rtmp_session_t *rsession, int amfnumber) { rtmp_state_t *state = &rsession->amfstate[amfnumber]; - //amf0_data *dump; +#ifdef RTMP_DEBUG_IO + amf0_data *dump; +#endif int i = 0; buffer_helper_t helper = { state->buf, 0, state->origlen }; int64_t transaction_id; @@ -188,6 +191,7 @@ switch_status_t rtmp_check_auth(rtmp_session_t *rsession, const char *user, cons switch_xml_t xml = NULL, x_param, x_params; switch_bool_t allow_empty_password = SWITCH_FALSE; const char *passwd = NULL; + switch_bool_t disallow_multiple_registration = SWITCH_FALSE; switch_event_t *locate_params; switch_event_create(&locate_params, SWITCH_EVENT_GENERAL); @@ -211,6 +215,9 @@ switch_status_t rtmp_check_auth(rtmp_session_t *rsession, const char *user, cons if (!strcasecmp(var, "allow-empty-password")) { allow_empty_password = switch_true(val); } + if (!strcasecmp(var, "disallow-multiple-registration")) { + disallow_multiple_registration = switch_true(val); + } } } @@ -231,6 +238,28 @@ switch_status_t rtmp_check_auth(rtmp_session_t *rsession, const char *user, cons } else { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_WARNING, "Authentication failed for %s@%s\n", user, domain); } + + if (disallow_multiple_registration) { + switch_hash_index_t *hi; + switch_thread_rwlock_rdlock(rsession->profile->session_rwlock); + for (hi = switch_hash_first(NULL, rsession->profile->session_hash); hi; hi = switch_hash_next(hi)) { + void *val; + const void *key; + switch_ssize_t keylen; + rtmp_session_t *item; + switch_hash_this(hi, &key, &keylen, &val); + + item = (rtmp_session_t *)val; + if (rtmp_session_check_user(item, user, domain) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_INFO, "Logging out %s@%s on RTMP sesssion [%s]\n", user, domain, item->uuid); + if (rtmp_session_logout(item, user, domain) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_ERROR, "Unable to logout %s@%s on RTMP sesssion [%s]\n", user, domain, item->uuid); + } + } + + } + switch_thread_rwlock_unlock(rsession->profile->session_rwlock); + } done: if (xml) { @@ -612,7 +641,7 @@ switch_status_t rtmp_send_message(rtmp_session_t *rsession, uint8_t amfnumber, u } end: switch_mutex_unlock(rsession->socket_mutex); - return SWITCH_STATUS_SUCCESS; + return status; } /* Returns SWITCH_STATUS_SUCCESS of the connection is still active or SWITCH_STATUS_FALSE to tear it down */ @@ -858,10 +887,18 @@ switch_status_t rtmp_handle_data(rtmp_session_t *rsession) uint16_t len = state->origlen; switch_mutex_lock(rsession->tech_pvt->readbuf_mutex); - if (rsession->tech_pvt->maxlen && switch_buffer_inuse(rsession->tech_pvt->readbuf) > rsession->tech_pvt->maxlen * 3) { + if (rsession->tech_pvt->maxlen && switch_buffer_inuse(rsession->tech_pvt->readbuf) > rsession->tech_pvt->maxlen * 40) { + rsession->tech_pvt->over_size++; + } else { + rsession->tech_pvt->over_size = 0; + } + if (rsession->tech_pvt->over_size > 10) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, + "%s buffer > %u for 10 consecutive packets... Flushing buffer\n", + switch_core_session_get_name(rsession->tech_pvt->session), rsession->tech_pvt->maxlen * 40); switch_buffer_zero(rsession->tech_pvt->readbuf); #ifdef RTMP_DEBUG_IO - fprintf(rsession->io_debug_in, "[chunk_stream=%d type=0x%x ts=%d stream_id=0x%x] FLUSH BUFFER [exceeded %u]\n", rsession->amfnumber, state->type, (int)state->ts, state->stream_id, rsession->tech_pvt->maxlen * 3); + fprintf(rsession->io_debug_in, "[chunk_stream=%d type=0x%x ts=%d stream_id=0x%x] FLUSH BUFFER [exceeded %u]\n", rsession->amfnumber, state->type, (int)state->ts, state->stream_id, rsession->tech_pvt->maxlen * 5); #endif } switch_buffer_write(rsession->tech_pvt->readbuf, &len, 2); diff --git a/src/mod/endpoints/mod_rtmp/rtmp_tcp.c b/src/mod/endpoints/mod_rtmp/rtmp_tcp.c index 62bb709b01..7d4bbd5465 100644 --- a/src/mod/endpoints/mod_rtmp/rtmp_tcp.c +++ b/src/mod/endpoints/mod_rtmp/rtmp_tcp.c @@ -85,7 +85,10 @@ static switch_status_t rtmp_tcp_read(rtmp_session_t *rsession, unsigned char *bu switch_size_t olen = *len; #endif switch_assert(*len > 0 && *len < 1024000); - status = switch_socket_recv(io_pvt->socket, (char*)buf, len); + + do { + status = switch_socket_recv(io_pvt->socket, (char*)buf, len); + } while(status != SWITCH_STATUS_SUCCESS && SWITCH_STATUS_IS_BREAK(status)); #ifdef RTMP_DEBUG_IO { @@ -197,10 +200,10 @@ void *SWITCH_THREAD_FUNC rtmp_io_tcp_thread(switch_thread_t *thread, void *obj) switch_mutex_unlock(io->mutex); if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_TIMEOUT) { - //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "pollset_poll failed\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "pollset_poll failed\n"); continue; } else if (status == SWITCH_STATUS_TIMEOUT) { - switch_yield(1); + switch_cond_next(); } for (i = 0; i < numfds; i++) { @@ -219,6 +222,10 @@ void *SWITCH_THREAD_FUNC rtmp_io_tcp_thread(switch_thread_t *thread, void *obj) if (switch_socket_opt_set(newsocket, SWITCH_SO_NONBLOCK, TRUE)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't set socket as non-blocking\n"); } + + if (switch_socket_opt_set(newsocket, SWITCH_SO_TCP_NODELAY, 1)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't disable Nagle.\n"); + } if (rtmp_session_request(io->base.profile, &newsession) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "RTMP session request failed\n"); @@ -314,6 +321,9 @@ switch_status_t rtmp_tcp_init(rtmp_profile_t *profile, const char *bindaddr, rtm if (switch_socket_opt_set(io_tcp->listen_socket, SWITCH_SO_REUSEADDR, 1)) { goto fail; } + if (switch_socket_opt_set(io_tcp->listen_socket, SWITCH_SO_TCP_NODELAY, 1)) { + goto fail; + } if (switch_socket_bind(io_tcp->listen_socket, sa)) { goto fail; } diff --git a/src/mod/endpoints/mod_skypopen/oss/main.c b/src/mod/endpoints/mod_skypopen/oss/main.c index 10ebfc9899..d92d2dc863 100644 --- a/src/mod/endpoints/mod_skypopen/oss/main.c +++ b/src/mod/endpoints/mod_skypopen/oss/main.c @@ -146,7 +146,11 @@ struct skypopen_listitem { /* The list of devices, and a lock to protect it */ static LIST_HEAD(skypopen_c_list); +#ifdef WANT_DEFINE_SPINLOCK +static DEFINE_SPINLOCK(skypopen_c_lock); +#else // WANT_DEFINE_SPINLOCK static spinlock_t skypopen_c_lock = SPIN_LOCK_UNLOCKED; +#endif // WANT_DEFINE_SPINLOCK /* Look for a device or create one if missing */ static struct skypopen_dev *skypopen_c_lookfor_device(dev_t key) diff --git a/src/mod/endpoints/mod_skypopen/oss/skypopen.h b/src/mod/endpoints/mod_skypopen/oss/skypopen.h index de38c791c9..dca1f8870d 100644 --- a/src/mod/endpoints/mod_skypopen/oss/skypopen.h +++ b/src/mod/endpoints/mod_skypopen/oss/skypopen.h @@ -31,6 +31,10 @@ #define WANT_HRTIMER #endif /* HRTIMER */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) +#define WANT_DEFINE_SPINLOCK +#endif /* DEFINE_SPINLOCK */ + #define SKYPOPEN_BLK 1920 #define SKYPOPEN_SLEEP 20 diff --git a/src/mod/endpoints/mod_sofia/Makefile.am b/src/mod/endpoints/mod_sofia/Makefile.am index 5825fc7f5c..fb0ab25e0b 100644 --- a/src/mod/endpoints/mod_sofia/Makefile.am +++ b/src/mod/endpoints/mod_sofia/Makefile.am @@ -9,7 +9,7 @@ SOFIAUA_BUILDDIR=$(SOFIA_BUILDDIR)/libsofia-sip-ua SOFIALA=$(SOFIAUA_BUILDDIR)/libsofia-sip-ua.la mod_LTLIBRARIES = mod_sofia.la -mod_sofia_la_SOURCES = mod_sofia.c sofia.c sofia_glue.c sofia_presence.c sofia_reg.c sofia_sla.c sip-dig.c mod_sofia.h +mod_sofia_la_SOURCES = mod_sofia.c sofia.c sofia_glue.c sofia_presence.c sofia_reg.c sip-dig.c mod_sofia.h mod_sofia_la_CFLAGS = $(AM_CFLAGS) -I. $(SOFIA_CMD_LINE_CFLAGS) mod_sofia_la_CFLAGS += -I$(SOFIAUA_DIR)/bnf -I$(SOFIAUA_BUILDDIR)/bnf mod_sofia_la_CFLAGS += -I$(SOFIAUA_DIR)/http -I$(SOFIAUA_BUILDDIR)/http diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.2008.vcproj b/src/mod/endpoints/mod_sofia/mod_sofia.2008.vcproj index e6490f13dd..616ebd87a4 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.2008.vcproj +++ b/src/mod/endpoints/mod_sofia/mod_sofia.2008.vcproj @@ -321,10 +321,6 @@ RelativePath=".\sofia_reg.c" > - - diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.2010.vcxproj b/src/mod/endpoints/mod_sofia/mod_sofia.2010.vcxproj index ab53d06524..736cea580b 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.2010.vcxproj +++ b/src/mod/endpoints/mod_sofia/mod_sofia.2010.vcxproj @@ -143,7 +143,6 @@ - diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index dd64504d40..493ce3a701 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -250,6 +250,11 @@ char *generate_pai_str(private_object_t *tech_pvt) const char *callee_name = NULL, *callee_number = NULL; const char *var, *header, *ua = switch_channel_get_variable(tech_pvt->channel, "sip_user_agent"); char *pai = NULL; + const char *host = switch_channel_get_variable(tech_pvt->channel, "sip_to_host"); + + if (zstr(host)) { + host = tech_pvt->profile->sipip; + } if (!sofia_test_pflag(tech_pvt->profile, PFLAG_PASS_CALLEE_ID) || !sofia_test_pflag(tech_pvt->profile, PFLAG_CID_IN_1XX) || ((var = switch_channel_get_variable(tech_pvt->channel, "sip_cid_in_1xx")) && switch_false(var))) { @@ -276,7 +281,7 @@ char *generate_pai_str(private_object_t *tech_pvt) callee_name = switch_sanitize_number(switch_core_session_strdup(session, callee_name)); if (!zstr(callee_number) && (zstr(ua) || !switch_stristr("polycom", ua))) { - callee_number = switch_core_session_sprintf(session, "sip:%s@%s", callee_number, tech_pvt->profile->sipip); + callee_number = switch_core_session_sprintf(session, "sip:%s@%s", callee_number, host); } header = (tech_pvt->cid_type == CID_TYPE_RPID && !switch_stristr("aastra", ua)) ? "Remote-Party-ID" : "P-Asserted-Identity"; @@ -321,8 +326,11 @@ static int hangup_cause_to_sip(switch_call_cause_t cause) case SWITCH_CAUSE_REDIRECTION_TO_NEW_DESTINATION: return 410; case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER: + case SWITCH_CAUSE_INVALID_PROFILE: return 502; case SWITCH_CAUSE_INVALID_NUMBER_FORMAT: + case SWITCH_CAUSE_INVALID_URL: + case SWITCH_CAUSE_INVALID_GATEWAY: return 484; case SWITCH_CAUSE_FACILITY_REJECTED: return 501; @@ -333,6 +341,7 @@ static int hangup_cause_to_sip(switch_call_cause_t cause) case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER: case SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE: case SWITCH_CAUSE_SWITCH_CONGESTION: + case SWITCH_CAUSE_GATEWAY_DOWN: return 503; case SWITCH_CAUSE_OUTGOING_CALL_BARRED: case SWITCH_CAUSE_INCOMING_CALL_BARRED: @@ -484,11 +493,12 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session) const char *val = NULL; val = switch_channel_get_variable(tech_pvt->channel, "disable_q850_reason"); - if (!val || switch_true(val)) { - if (cause > 0 && cause < 128) { - switch_snprintf(reason, sizeof(reason), "Q.850;cause=%d;text=\"%s\"", cause, switch_channel_cause2str(cause)); - } else if (cause == SWITCH_CAUSE_PICKED_OFF || cause == SWITCH_CAUSE_LOSE_RACE) { + + if (switch_false(val)) { + if (switch_channel_test_flag(channel, CF_INTERCEPT) || cause == SWITCH_CAUSE_PICKED_OFF || cause == SWITCH_CAUSE_LOSE_RACE) { switch_snprintf(reason, sizeof(reason), "SIP;cause=200;text=\"Call completed elsewhere\""); + } else if (cause > 0 && cause < 128) { + switch_snprintf(reason, sizeof(reason), "Q.850;cause=%d;text=\"%s\"", cause, switch_channel_cause2str(cause)); } else { switch_snprintf(reason, sizeof(reason), "%s;cause=%d;text=\"%s\"", tech_pvt->profile->username, cause, switch_channel_cause2str(cause)); } @@ -952,7 +962,6 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f while (!(tech_pvt->read_codec.implementation && switch_rtp_ready(tech_pvt->rtp_session) && !switch_channel_test_flag(channel, CF_REQ_MEDIA))) { switch_ivr_parse_all_messages(tech_pvt->session); - if (--sanity && switch_channel_up(channel)) { switch_yield(10000); } else { @@ -1009,39 +1018,66 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f switch_event_t *event; if (switch_event_create(&event, SWITCH_EVENT_RECV_RTCP_MESSAGE) == SWITCH_STATUS_SUCCESS) { - char buf[30]; + char value[30]; + char header[50]; + int i; char *uuid = switch_core_session_get_uuid(session); if (uuid) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(session)); } - snprintf(buf, sizeof(buf), "%.8x", rtcp_frame.ssrc); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "SSRC", buf); + snprintf(value, sizeof(value), "%.8x", rtcp_frame.ssrc); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "SSRC", value); - snprintf(buf, sizeof(buf), "%u", rtcp_frame.ntp_msw); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "NTP-Most-Significant-Word", buf); + snprintf(value, sizeof(value), "%u", rtcp_frame.ntp_msw); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "NTP-Most-Significant-Word", value); - snprintf(buf, sizeof(buf), "%u", rtcp_frame.ntp_lsw); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "NTP-Least-Significant-Word", buf); + snprintf(value, sizeof(value), "%u", rtcp_frame.ntp_lsw); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "NTP-Least-Significant-Word", value); - snprintf(buf, sizeof(buf), "%u", rtcp_frame.timestamp); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTP-Timestamp", buf); + snprintf(value, sizeof(value), "%u", rtcp_frame.timestamp); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTP-Timestamp", value); - snprintf(buf, sizeof(buf), "%u", rtcp_frame.packet_count); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Sender-Packet-Count", buf); + snprintf(value, sizeof(value), "%u", rtcp_frame.packet_count); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Sender-Packet-Count", value); - snprintf(buf, sizeof(buf), "%u", rtcp_frame.octect_count); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Octect-Packet-Count", buf); + snprintf(value, sizeof(value), "%u", rtcp_frame.octect_count); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Octect-Packet-Count", value); - snprintf(buf, sizeof(buf), "%" SWITCH_SIZE_T_FMT, tech_pvt->read_frame.timestamp); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Last-RTP-Timestamp", buf); + snprintf(value, sizeof(value), "%" SWITCH_SIZE_T_FMT, tech_pvt->read_frame.timestamp); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Last-RTP-Timestamp", value); - snprintf(buf, sizeof(buf), "%u", tech_pvt->read_frame.rate); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTP-Rate", buf); + snprintf(value, sizeof(value), "%u", tech_pvt->read_frame.rate); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTP-Rate", value); - snprintf(buf, sizeof(buf), "%" SWITCH_TIME_T_FMT, switch_time_now()); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Capture-Time", buf); + snprintf(value, sizeof(value), "%" SWITCH_TIME_T_FMT, switch_time_now()); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Capture-Time", value); + + // Add sources info + for (i = 0; i < rtcp_frame.report_count; i++) { + snprintf(header, sizeof(header), "Source%u-SSRC", i); + snprintf(value, sizeof(value), "%.8x", rtcp_frame.reports[i].ssrc); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value); + snprintf(header, sizeof(header), "Source%u-Fraction", i); + snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].fraction); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value); + snprintf(header, sizeof(header), "Source%u-Lost", i); + snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].lost); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value); + snprintf(header, sizeof(header), "Source%u-Highest-Sequence-Number-Received", i); + snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].highest_sequence_number_received); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value); + snprintf(header, sizeof(header), "Source%u-Jitter", i); + snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].jitter); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value); + snprintf(header, sizeof(header), "Source%u-LSR", i); + snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].lsr); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value); + snprintf(header, sizeof(header), "Source%u-DLSR", i); + snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].dlsr); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value); + } switch_event_fire(&event); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10, "Dispatched RTCP event\n"); @@ -1504,6 +1540,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames) (%d max frames) (%d max drift)\n", len, qlen, maxqlen, max_drift); switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER); + if (!switch_false(switch_channel_get_variable(tech_pvt->channel, "sip_jitter_buffer_plc"))) { + switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER_PLC); + } } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_WARNING, "Error Setting Jitterbuffer to %dms (%d frames)\n", len, qlen); @@ -1782,6 +1821,28 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi } break; + case SWITCH_MESSAGE_INDICATE_AUDIO_DATA: + { + if (switch_rtp_ready(tech_pvt->rtp_session)) { + if (msg->numeric_arg) { + if (switch_channel_test_flag(tech_pvt->channel, CF_JITTERBUFFER)) { + switch_rtp_pause_jitter_buffer(tech_pvt->rtp_session, SWITCH_TRUE); + sofia_set_flag(tech_pvt, TFLAG_JB_PAUSED); + } + + rtp_flush_read_buffer(tech_pvt->rtp_session, SWITCH_RTP_FLUSH_UNSTICK); + + } else { + if (sofia_test_flag(tech_pvt, TFLAG_JB_PAUSED)) { + sofia_clear_flag(tech_pvt, TFLAG_JB_PAUSED); + if (switch_channel_test_flag(tech_pvt->channel, CF_JITTERBUFFER)) { + switch_rtp_pause_jitter_buffer(tech_pvt->rtp_session, SWITCH_FALSE); + } + } + } + } + } + break; case SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT: { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Sending media re-direct:\n%s\n", @@ -1793,7 +1854,10 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi } sofia_set_flag_locked(tech_pvt, TFLAG_SENT_UPDATE); - switch_channel_set_flag(channel, CF_REQ_MEDIA); + + if (!switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { + switch_channel_set_flag(channel, CF_REQ_MEDIA); + } sofia_glue_do_invite(session); } break; @@ -1854,7 +1918,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi sofia_glue_set_image_sdp(tech_pvt, t38_options, msg->numeric_arg); - switch_channel_set_flag(channel, CF_REQ_MEDIA); + if (!switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { + switch_channel_set_flag(channel, CF_REQ_MEDIA); + } sofia_set_flag_locked(tech_pvt, TFLAG_SENT_UPDATE); sofia_glue_do_invite(session); } @@ -1892,7 +1958,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi sofia_glue_set_local_sdp(tech_pvt, NULL, 0, NULL, 1); if (send_invite) { - switch_channel_set_flag(channel, CF_REQ_MEDIA); + if (!switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { + switch_channel_set_flag(channel, CF_REQ_MEDIA); + } sofia_glue_do_invite(session); } else { status = SWITCH_STATUS_FALSE; @@ -1918,6 +1986,43 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi } else { nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), NUTAG_SUBSTATE(nua_substate_active), SIPTAG_EVENT_STR(event), TAG_END()); } + + } + case SWITCH_MESSAGE_INDICATE_INFO: + { + char *ct = "freeswitch/data"; + int ok = 0; + + if (!zstr(msg->string_array_arg[0]) && !zstr(msg->string_array_arg[1])) { + ct = switch_core_session_sprintf(session, "%s/%s", msg->string_array_arg[0], msg->string_array_arg[1]); + ok = 1; + } + + if (switch_stristr("send_info", tech_pvt->x_freeswitch_support_remote)) { + ok = 1; + } + + if (switch_true(switch_channel_get_variable(channel, "fs_send_unspported_info"))) { + ok = 1; + } + + if (ok) { + char *headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_INFO_HEADER_PREFIX); + const char *pl = NULL; + + if (!zstr(msg->string_array_arg[2])) { + pl = msg->string_array_arg[2]; + } + + nua_info(tech_pvt->nh, + SIPTAG_CONTENT_TYPE_STR(ct), + TAG_IF(!zstr(headers), SIPTAG_HEADER_STR(headers)), + TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), + TAG_IF(pl, SIPTAG_PAYLOAD_STR(pl)), + TAG_END()); + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s send_info is not supported.\n", switch_channel_get_name(channel)); + } } break; case SWITCH_MESSAGE_INDICATE_SIMPLIFY: @@ -1989,6 +2094,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi const char *ua = switch_channel_get_variable(tech_pvt->channel, "sip_user_agent"); switch_event_t *event; + check_decode(name, tech_pvt->session); + + if (zstr(number)) { number = tech_pvt->caller_profile->destination_number; } @@ -2306,7 +2414,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { sofia_glue_tech_patch_sdp(tech_pvt); - sofia_glue_tech_proxy_remote_addr(tech_pvt); + sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL); } if (sofia_use_soa(tech_pvt)) { nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh), reason), SIPTAG_CONTACT_STR(tech_pvt->reply_contact), @@ -2569,7 +2677,7 @@ static switch_status_t sofia_receive_event(switch_core_session_t *session, switc switch_mutex_lock(tech_pvt->sofia_mutex); msg_nh = nua_handle(tech_pvt->profile->nua, NULL, SIPTAG_FROM_STR(tech_pvt->chat_from), - NUTAG_URL(tech_pvt->chat_to), SIPTAG_TO_STR(tech_pvt->chat_to), SIPTAG_CONTACT_STR(tech_pvt->profile->url), TAG_END()); + NUTAG_URL(tech_pvt->chat_to), SIPTAG_TO_STR(tech_pvt->chat_to), TAG_END()); nua_handle_bind(msg_nh, &mod_sofia_globals.destroy_private); nua_message(msg_nh, SIPTAG_CONTENT_TYPE_STR("text/html"), SIPTAG_PAYLOAD_STR(body), TAG_END()); switch_mutex_unlock(tech_pvt->sofia_mutex); @@ -2867,7 +2975,6 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t stream->write_function(stream, "CALLS-OUT \t%u\n", profile->ob_calls); stream->write_function(stream, "FAILED-CALLS-OUT \t%u\n", profile->ob_failed_calls); } - stream->write_function(stream, "\nRegistrations:\n%s\n", line); cb.profile = profile; cb.stream = stream; @@ -2884,6 +2991,12 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t "network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host" " from sip_registrations where profile_name='%q' and contact like '%%%q%%'", profile->name, argv[3]); } + if (!sql && argv[2] && !strcasecmp(argv[2], "reg")) { + sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status," + "rpid,expires,user_agent,server_user,server_host,profile_name,hostname," + "network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host" + " from sip_registrations where profile_name='%q'", profile->name); + } if (!sql && argv[2] && !strcasecmp(argv[2], "user") && argv[3]) { char *dup = strdup(argv[3]); char *host = NULL, *user = NULL; @@ -2914,20 +3027,18 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t switch_safe_free(sqlextra); } - if (!sql) { - sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status," - "rpid,expires,user_agent,server_user,server_host,profile_name,hostname," - "network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host" - " from sip_registrations where profile_name='%q'", profile->name); + if (sql) { + stream->write_function(stream, "\nRegistrations:\n%s\n", line); + + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, show_reg_callback, &cb); + switch_safe_free(sql); + + stream->write_function(stream, "Total items returned: %d\n", cb.row_process); + stream->write_function(stream, "%s\n", line); } - sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, show_reg_callback, &cb); - switch_safe_free(sql); - - stream->write_function(stream, "Total items returned: %d\n", cb.row_process); - stream->write_function(stream, "%s\n", line); - sofia_glue_release_profile(profile); + } else { stream->write_function(stream, "Invalid Profile!\n"); } @@ -4070,7 +4181,7 @@ SWITCH_STANDARD_API(sofia_function) " siptrace \n" " capture \n" " watchdog \n\n" - "sofia profile [reg ] | [pres ] | [user ]\n" + "sofia profile [reg []] | [pres ] | [user ]\n" "sofia gateway \n\n" "sofia loglevel [0-9]\n" "sofia tracelevel \n\n" @@ -4130,6 +4241,7 @@ SWITCH_STANDARD_API(sofia_function) int ston = -1; int cton = -1; int wdon = -1; + int stbyon = -1; if (argc > 1) { if (!strcasecmp(argv[1], "debug")) { @@ -4165,6 +4277,12 @@ SWITCH_STANDARD_API(sofia_function) } } + if (!strcasecmp(argv[1], "standby")) { + if (argc > 2) { + stbyon = switch_true(argv[2]); + } + } + if (!strcasecmp(argv[1], "capture")) { if (argc > 2) { cton = switch_true(argv[2]); @@ -4182,11 +4300,14 @@ SWITCH_STANDARD_API(sofia_function) sofia_glue_global_siptrace(ston); stream->write_function(stream, "+OK Global siptrace %s", ston ? "on" : "off"); } else if (cton != -1) { - sofia_glue_global_capture(cton); - stream->write_function(stream, "+OK Global capture %s", cton ? "on" : "off"); + sofia_glue_global_capture(cton); + stream->write_function(stream, "+OK Global capture %s", cton ? "on" : "off"); } else if (wdon != -1) { sofia_glue_global_watchdog(wdon); stream->write_function(stream, "+OK Global watchdog %s", wdon ? "on" : "off"); + } else if (stbyon != -1) { + sofia_glue_global_standby(stbyon); + stream->write_function(stream, "+OK Global standby %s", stbyon ? "on" : "off"); } else { stream->write_function(stream, "-ERR Usage: siptrace |capture |watchdog |debug write_function(stream, "Flushing recovery database.\n"); } else { int x = sofia_glue_recover(SWITCH_FALSE); + switch_event_t *event = NULL; if (x) { + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, + MY_EVENT_RECOVERY_RECOVERED) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "recovered_calls", "%d", x); + switch_event_fire(&event); + } + stream->write_function(stream, "Recovered %d call(s)\n", x); } else { + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, + MY_EVENT_RECOVERY_RECOVERED) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "recovered_calls", "0"); + switch_event_fire(&event); + } + stream->write_function(stream, "No calls to recover.\n"); } } @@ -4275,7 +4409,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session *new_session = NULL; if (!outbound_profile || zstr(outbound_profile->destination_number)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Invalid Destination\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Invalid Empty Destination\n"); goto error; } @@ -4312,30 +4446,30 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session char *gw, *params; if (!(gw = strchr(profile_name, '/'))) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid URL\n"); - cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT; + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid URL \'%s\'\n", profile_name); + cause = SWITCH_CAUSE_INVALID_URL; goto error; } *gw++ = '\0'; if (!(dest = strchr(gw, '/'))) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid URL\n"); - cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT; + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid URL \'%s\'\n", gw); + cause = SWITCH_CAUSE_INVALID_URL; goto error; } *dest++ = '\0'; if (!(gateway_ptr = sofia_reg_find_gateway(gw))) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Gateway\n"); - cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT; + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Gateway \'%s\'\n", gw); + cause = SWITCH_CAUSE_INVALID_GATEWAY; goto error; } if (gateway_ptr->status != SOFIA_GATEWAY_UP) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Gateway is down!\n"); - cause = SWITCH_CAUSE_NETWORK_OUT_OF_ORDER; + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Gateway \'%s\' is down!\n", gw); + cause = SWITCH_CAUSE_GATEWAY_DOWN; gateway_ptr->ob_failed_calls++; goto error; } @@ -4375,6 +4509,13 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session } profile = gateway_ptr->profile; + + if (profile && sofia_test_pflag(profile, PFLAG_STANDBY)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "System Paused\n"); + cause = SWITCH_CAUSE_SYSTEM_SHUTDOWN; + goto error; + } + tech_pvt->gateway_name = switch_core_session_strdup(nsession, gateway_ptr->name); switch_channel_set_variable(nchannel, "sip_gateway_name", gateway_ptr->name); @@ -4442,14 +4583,20 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session } else { if (!(dest = strchr(profile_name, '/'))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid URL\n"); - cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT; + cause = SWITCH_CAUSE_INVALID_URL; goto error; } *dest++ = '\0'; if (!(profile = sofia_glue_find_profile(profile_name))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Profile\n"); - cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; + cause = SWITCH_CAUSE_INVALID_PROFILE; + goto error; + } + + if (profile && sofia_test_pflag(profile, PFLAG_STANDBY)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "System Paused\n"); + cause = SWITCH_CAUSE_SYSTEM_SHUTDOWN; goto error; } @@ -4562,6 +4709,8 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session if (profile->pres_type) { char *sql; + time_t now; + const char *presence_id = switch_channel_get_variable(nchannel, "presence_id"); const char *presence_data = switch_channel_get_variable(nchannel, "presence_data"); @@ -4573,9 +4722,10 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session presence_data = switch_event_get_header(var_event, "presence_data"); } - sql = switch_mprintf("insert into sip_dialogs (uuid,presence_id,presence_data,profile_name,hostname) " - "values ('%q', '%q', '%q', '%q', '%q')", switch_core_session_get_uuid(nsession), - switch_str_nil(presence_id), switch_str_nil(presence_data), profile->name, mod_sofia_globals.hostname); + now = switch_epoch_time_now(NULL); + sql = switch_mprintf("insert into sip_dialogs (uuid,presence_id,presence_data,profile_name,hostname,rcd) " + "values ('%q', '%q', '%q', '%q', '%q', %ld)", switch_core_session_get_uuid(nsession), + switch_str_nil(presence_id), switch_str_nil(presence_data), profile->name, mod_sofia_globals.hostname, (long) now); sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); switch_safe_free(sql); } @@ -5381,6 +5531,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load) switch_console_set_complete("add sofia tracelevel ::[console:alert:crit:err:warning:notice:info:debug"); switch_console_set_complete("add sofia global siptrace ::[on:off"); + switch_console_set_complete("add sofia global standby ::[on:off"); switch_console_set_complete("add sofia global capture ::[on:off"); switch_console_set_complete("add sofia global watchdog ::[on:off"); @@ -5495,3 +5646,4 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sofia_shutdown) * For VIM: * vim:set softtabstop=4 shiftwidth=4 tabstop=4: */ + diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 3ca737dc2e..1bf9ef923f 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -87,6 +87,7 @@ typedef struct private_object private_object_t; #define MY_EVENT_GATEWAY_DEL "sofia::gateway_delete" #define MY_EVENT_RECOVERY "sofia::recovery_recv" #define MY_EVENT_RECOVERY_SEND "sofia::recovery_send" +#define MY_EVENT_RECOVERY_RECOVERED "sofia::recovery_recovered" #define MULTICAST_EVENT "multicast::event" #define SOFIA_REPLACES_HEADER "_sofia_replaces_" @@ -95,6 +96,8 @@ typedef struct private_object private_object_t; #define SOFIA_MULTIPART_PREFIX "sip_mp_" #define SOFIA_MULTIPART_PREFIX_T "~sip_mp_" #define SOFIA_SIP_HEADER_PREFIX "sip_h_" +#define SOFIA_SIP_INFO_HEADER_PREFIX "sip_info_h_" +#define SOFIA_SIP_INFO_HEADER_PREFIX_T "~sip_info_h_" #define SOFIA_SIP_RESPONSE_HEADER_PREFIX "sip_rh_" #define SOFIA_SIP_RESPONSE_HEADER_PREFIX_T "~sip_rh_" #define SOFIA_SIP_BYE_HEADER_PREFIX "sip_bye_h_" @@ -109,7 +112,7 @@ typedef struct private_object private_object_t; #define SOFIA_SECURE_MEDIA_CONFIRMED_VARIABLE "sip_secure_media_confirmed" #define SOFIA_HAS_CRYPTO_VARIABLE "sip_has_crypto" #define SOFIA_CRYPTO_MANDATORY_VARIABLE "sip_crypto_mandatory" -#define FREESWITCH_SUPPORT "update_display" +#define FREESWITCH_SUPPORT "update_display,send_info" #include #include @@ -128,6 +131,9 @@ typedef struct private_object private_object_t; #include "sofia-sip/sip_parser.h" #include "sofia-sip/tport_tag.h" #include +#ifndef WIN32 +#include +#endif typedef enum { DTMF_2833, @@ -200,6 +206,7 @@ typedef enum { PFLAG_WORKER_RUNNING, PFLAG_UNREG_OPTIONS_FAIL, PFLAG_DISABLE_TIMER, + PFLAG_ENABLE_RFC5626, PFLAG_DISABLE_100REL, PFLAG_AGGRESSIVE_NAT_DETECTION, PFLAG_RECIEVED_IN_NAT_REG_CONTACT, @@ -214,7 +221,7 @@ typedef enum { PFLAG_UUID_AS_CALLID, PFLAG_SCROOGE, PFLAG_MANAGE_SHARED_APPEARANCE, - PFLAG_MANAGE_SHARED_APPEARANCE_SYLANTRO, + PFLAG_STANDBY, PFLAG_DISABLE_SRV, PFLAG_DISABLE_SRV503, PFLAG_DISABLE_NAPTR, @@ -230,6 +237,7 @@ typedef enum { PFLAG_AUTO_NAT, PFLAG_SIPCOMPACT, PFLAG_SQL_IN_TRANS, + PFLAG_PRESENCE_PRIVACY, PFLAG_PASS_CALLEE_ID, PFLAG_LOG_AUTH_FAIL, PFLAG_FORWARD_MWI_NOTIFY, @@ -253,6 +261,8 @@ typedef enum { PFLAG_AUTO_ASSIGN_PORT, PFLAG_AUTO_ASSIGN_TLS_PORT, PFLAG_SHUTDOWN, + PFLAG_PRESENCE_MAP, + PFLAG_OPTIONS_RESPOND_503_ON_BUSY, /* No new flags below this line */ PFLAG_MAX } PFLAGS; @@ -472,6 +482,7 @@ struct sofia_gateway { int32_t retry_seconds; int32_t reg_timeout_seconds; int32_t failure_status; + sub_state_t sub_state; reg_state_t state; switch_memory_pool_t *pool; int deleted; @@ -543,6 +554,7 @@ struct sofia_profile { char *record_template; char *record_path; char *presence_hosts; + char *presence_privacy; char *challenge_realm; char *rtcp_audio_interval_msec; char *rtcp_video_interval_msec; @@ -625,6 +637,8 @@ struct sofia_profile { uint32_t event_timeout; int watchdog_enabled; switch_mutex_t *gw_mutex; + uint32_t queued_events; + uint32_t cseq_base; }; struct private_object { @@ -790,6 +804,7 @@ typedef enum { AUTH_OK, AUTH_FORBIDDEN, AUTH_STALE, + AUTH_RENEWED, } auth_res_t; typedef struct { @@ -830,6 +845,8 @@ switch_mutex_unlock(obj->flag_mutex); /* Function Prototypes */ /*************************************************************************************************************************************************************/ +void sofia_glue_global_standby(switch_bool_t on); + switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_flag_t myflags); void sofia_glue_deactivate_rtp(private_object_t *tech_pvt); @@ -1033,7 +1050,7 @@ int sofia_glue_transport_has_tls(const sofia_transport_t tp); const char *sofia_glue_get_unknown_header(sip_t const *sip, const char *name); switch_status_t sofia_glue_build_crypto(private_object_t *tech_pvt, int index, switch_rtp_crypto_key_type_t type, switch_rtp_crypto_direction_t direction); void sofia_glue_tech_patch_sdp(private_object_t *tech_pvt); -switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt); +switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt, const char *sdp_str); void sofia_presence_event_thread_start(void); void sofia_reg_expire_call_id(sofia_profile_t *profile, const char *call_id, int reboot); void sofia_reg_check_call_id(sofia_profile_t *profile, const char *call_id); @@ -1055,24 +1072,6 @@ switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force) void sofia_wait_for_reply(struct private_object *tech_pvt, nua_event_t event, uint32_t timeout); void sofia_glue_set_image_sdp(private_object_t *tech_pvt, switch_t38_options_t *t38_options, int insist); -/* - * SLA (shared line appearance) entrypoints - */ - -void sofia_sla_handle_register(nua_t *nua, sofia_profile_t *profile, sip_t const *sip, - sofia_dispatch_event_t *de, long exptime, const char *full_contact); -void sofia_sla_handle_sip_i_publish(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip, - sofia_dispatch_event_t *de, tagi_t tags[]); -void sofia_sla_handle_sip_i_subscribe(nua_t *nua, const char *contact_str, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip, - sofia_dispatch_event_t *de, tagi_t tags[]); -void sofia_sla_handle_sip_r_subscribe(int status, - char const *phrase, - nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip, - sofia_dispatch_event_t *de, - tagi_t tags[]); -void sofia_sla_handle_sip_i_notify(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip, - sofia_dispatch_event_t *de, tagi_t tags[]); - /* * Logging control functions */ @@ -1104,7 +1103,7 @@ void sofia_glue_free_destination(sofia_destination_t *dst); switch_status_t sofia_glue_send_notify(sofia_profile_t *profile, const char *user, const char *host, const char *event, const char *contenttype, const char *body, const char *o_contact, const char *network_ip); char *sofia_glue_get_extra_headers(switch_channel_t *channel, const char *prefix); -void sofia_glue_set_extra_headers(switch_channel_t *channel, sip_t const *sip, const char *prefix); +void sofia_glue_set_extra_headers(switch_core_session_t *session, sip_t const *sip, const char *prefix); void sofia_info_send_sipfrag(switch_core_session_t *aleg, switch_core_session_t *bleg); void sofia_update_callee_id(switch_core_session_t *session, sofia_profile_t *profile, sip_t const *sip, switch_bool_t send); void sofia_send_callee_id(switch_core_session_t *session, const char *name, const char *number); @@ -1135,4 +1134,5 @@ void sofia_glue_parse_rtp_bugs(switch_rtp_bug_flag_t *flag_pole, const char *str char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sofia_dispatch_event_t *de, sofia_nat_parse_t *np); void sofia_glue_pause_jitterbuffer(switch_core_session_t *session, switch_bool_t on); void sofia_process_dispatch_event(sofia_dispatch_event_t **dep); - +char *sofia_glue_get_host(const char *str, switch_memory_pool_t *pool); +void sofia_presence_check_subscriptions(sofia_profile_t *profile, time_t now); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 640f1b2d0e..c116acad4b 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -31,6 +31,7 @@ * Norman Brandinger * Raymond Chandler * Nathan Patrick + * Joseph Sullivan * * * sofia.c -- SOFIA SIP Endpoint (sofia code) @@ -89,7 +90,8 @@ void sofia_handle_sip_r_notify(switch_core_session_t *session, int status, if (status >= 300 && sip && sip->sip_call_id && (!sofia_private || !sofia_private->is_call)) { char *sql; - sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", sip->sip_call_id->i_id); + + sql = switch_mprintf("update sip_subscriptions set expires=%ld where call_id='%q'", (long) switch_epoch_time_now(NULL), sip->sip_call_id->i_id); switch_assert(sql != NULL); sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE); nua_handle_destroy(nh); @@ -182,15 +184,78 @@ static void extract_header_vars(sofia_profile_t *profile, sip_t const *sip, su_free(nh->nh_home, full); } } - if (sip->sip_via) { - if ((full = sip_header_as_string(nh->nh_home, (void *) sip->sip_via))) { - const char *v = switch_channel_get_variable(channel, "sip_full_via"); - if (!v) { - switch_channel_set_variable(channel, "sip_full_via", full); - } - su_free(nh->nh_home, full); + + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { + if (sip->sip_contact) { + char *c = sip_header_as_string(nh->nh_home, (void *) sip->sip_contact); + switch_channel_set_variable(channel, "sip_recover_contact", c); + su_free(nh->nh_home, c); } } + + if (sip->sip_record_route) { + sip_record_route_t *rrp; + switch_stream_handle_t stream = { 0 }; + int x = 0; + + SWITCH_STANDARD_STREAM(stream); + + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { + char *tmp[128] = { 0 }; + int y = 0; + + for(rrp = sip->sip_record_route; rrp; rrp = rrp->r_next) { + char *rr = sip_header_as_string(nh->nh_home, (void *) rrp); + tmp[y++] = rr; + if (y == 127) break; + } + + y--; + + while(y >= 0) { + stream.write_function(&stream, x == 0 ? "%s" : ",%s", tmp[y]); + su_free(nh->nh_home, tmp[y]); + y--; + x++; + } + + } else { + for(rrp = sip->sip_record_route; rrp; rrp = rrp->r_next) { + char *rr = sip_header_as_string(nh->nh_home, (void *) rrp); + + stream.write_function(&stream, x == 0 ? "%s" : ",%s", rr); + su_free(nh->nh_home, rr); + + x++; + } + } + + switch_channel_set_variable(channel, "sip_invite_record_route", (char *)stream.data); + free(stream.data); + } + + if (sip->sip_via) { + sip_via_t *vp; + switch_stream_handle_t stream = { 0 }; + int x = 0; + + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { + SWITCH_STANDARD_STREAM(stream); + + for(vp = sip->sip_via; vp; vp = vp->v_next) { + char *v = sip_header_as_string(nh->nh_home, (void *) vp); + + stream.write_function(&stream, x == 0 ? "%s" : ",%s", v); + su_free(nh->nh_home, v); + + x++; + } + + switch_channel_set_variable(channel, "sip_recover_via", (char *)stream.data); + free(stream.data); + } + } + if (sip->sip_from) { char *p = strip_quotes(sip->sip_from->a_display); @@ -203,6 +268,7 @@ static void extract_header_vars(sofia_profile_t *profile, sip_t const *sip, su_free(nh->nh_home, full); } } + if (sip->sip_to) { char *p = strip_quotes(sip->sip_to->a_display); @@ -274,21 +340,6 @@ void sofia_handle_sip_i_notify(switch_core_session_t *session, int status, goto error; } - /* the following could be refactored back to the calling event handler here in sofia.c XXX MTK */ - /* potentially interesting note: for Linksys shared appearance, we'll probably have to set up to get bare notifies - * and pass them inward to the sla handler. we'll have to set NUTAG_APPL_METHOD("NOTIFY") when creating - * nua, and also pick them off special elsewhere here in sofia.c - MTK - * *and* for Linksys, I believe they use "sa" as their magic appearance agent name for those blind notifies, so - * we'll probably have to change to match - */ - if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) { - - if (sip->sip_request->rq_url->url_user && !strncmp(sip->sip_request->rq_url->url_user, "sla-agent", sizeof("sla-agent"))) { - sofia_sla_handle_sip_i_notify(nua, profile, nh, sip, de, tags); - goto end; - } - } - /* Automatically return a 200 OK for Event: keep-alive */ if (!strcasecmp(sip->sip_event->o_type, "keep-alive")) { /* XXX MTK - is this right? in this case isn't sofia is already sending a 200 itself also? */ @@ -413,7 +464,7 @@ void sofia_handle_sip_i_notify(switch_core_session_t *session, int status, /* dispatch freeswitch event */ if (switch_event_create(&s_event, SWITCH_EVENT_NOTIFY_IN) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event", sip->sip_event->o_type); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "pl_data", sip->sip_payload->pl_data); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "pl_data", sip->sip_payload ? sip->sip_payload->pl_data : ""); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "sip_content_type", sip->sip_content_type->c_type); switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "port", "%d", sofia_private->gateway->profile->sip_port); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "module_name", "mod_sofia"); @@ -545,7 +596,6 @@ void sofia_handle_sip_i_bye(switch_core_session_t *session, int status, switch_snprintf(st, sizeof(st), "%d", status); switch_channel_set_variable(channel, "sip_term_status", st); switch_snprintf(st, sizeof(st), "sip:%d", status); - switch_channel_set_variable_partner(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, st); switch_channel_set_variable(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, st); if (phrase) { @@ -556,7 +606,7 @@ void sofia_handle_sip_i_bye(switch_core_session_t *session, int status, switch_channel_set_variable(channel, "sip_term_cause", st); extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_BYE_HEADER_PREFIX); - sofia_glue_set_extra_headers(channel, sip, SOFIA_SIP_BYE_HEADER_PREFIX); + sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_BYE_HEADER_PREFIX); if (!(vval = switch_channel_get_variable(channel, "sip_copy_custom_headers")) || switch_true(vval)) { switch_core_session_t *nsession = NULL; @@ -695,6 +745,7 @@ void sofia_update_callee_id(switch_core_session_t *session, sofia_profile_t *pro if ((val = sofia_glue_get_unknown_header(sip, "X-FS-Display-Name"))) { name = (char *) val; + check_decode(name, session); fs++; } @@ -806,8 +857,7 @@ static void our_sofia_event_callback(nua_event_t event, int locked = 0; int check_destroy = 1; - - if (sofia_private && sofia_private->de) { + if (sofia_private && sofia_private->is_call && sofia_private->de) { sofia_dispatch_event_t *qde = sofia_private->de; sofia_private->de = NULL; sofia_process_dispatch_event(&qde); @@ -874,7 +924,7 @@ static void our_sofia_event_callback(nua_event_t event, uint32_t sess_count = switch_core_session_count(); uint32_t sess_max = switch_core_session_limit(0); - if (sess_count >= sess_max || !sofia_test_pflag(profile, PFLAG_RUNNING) || !switch_core_ready()) { + if (sess_count >= sess_max || !sofia_test_pflag(profile, PFLAG_RUNNING) || !switch_core_ready_inbound()) { nua_respond(nh, 503, "Maximum Calls In Progress", SIPTAG_RETRY_AFTER_STR("300"), TAG_END()); //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No more sessions allowed at this time.\n"); @@ -883,7 +933,8 @@ static void our_sofia_event_callback(nua_event_t event, } } - if (sofia_test_pflag(profile, PFLAG_AUTH_ALL) && tech_pvt && tech_pvt->key && sip) { + + if (sofia_test_pflag(profile, PFLAG_AUTH_ALL) && tech_pvt && tech_pvt->key && sip && (event < nua_r_set_params || event > nua_r_authenticate)) { sip_authorization_t const *authorization = NULL; if (sip->sip_authorization) { @@ -900,7 +951,7 @@ static void our_sofia_event_callback(nua_event_t event, REG_INVITE, NULL, NULL, NULL); } - if (auth_res != AUTH_OK) { + if ((auth_res != AUTH_OK && auth_res != AUTH_RENEWED)) { //switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); nua_respond(nh, SIP_401_UNAUTHORIZED, TAG_END()); goto done; @@ -1136,7 +1187,8 @@ void sofia_process_dispatch_event(sofia_dispatch_event_t **dep) sofia_dispatch_event_t *de = *dep; nua_handle_t *nh = de->nh; nua_t *nua = de->nua; - + sofia_profile_t *profile = de->profile; + *dep = NULL; our_sofia_event_callback(de->data->e_event, de->data->e_status, de->data->e_phrase, de->nua, de->profile, @@ -1144,6 +1196,10 @@ void sofia_process_dispatch_event(sofia_dispatch_event_t **dep) nua_destroy_event(de->event); su_free(nh->nh_home, de); + + switch_mutex_lock(profile->flag_mutex); + profile->queued_events--; + switch_mutex_unlock(profile->flag_mutex); nua_handle_unref(nh); nua_stack_unref(nua); @@ -1244,6 +1300,19 @@ void sofia_event_callback(nua_event_t event, { sofia_dispatch_event_t *de; + + if (sofia_test_pflag(profile, PFLAG_STANDBY)) { + if (event < nua_r_set_params || event > nua_r_authenticate) { + nua_respond(nh, 503, "System Paused", TAG_END()); + } + return; + } + + + switch_mutex_lock(profile->flag_mutex); + profile->queued_events++; + switch_mutex_unlock(profile->flag_mutex); + de = su_alloc(nh->nh_home, sizeof(*de)); memset(de, 0, sizeof(*de)); nua_save_event(nua, de->event); @@ -1524,6 +1593,12 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread /* While we're running, or there is a pending sql statment that we haven't appended to sqlbuf yet, because of a lack of buffer space */ while ((mod_sofia_globals.running == 1 && sofia_test_pflag(profile, PFLAG_RUNNING)) || sql) { + + if (sofia_test_pflag(profile, PFLAG_STANDBY)) { + switch_yield(1000000); + continue; + } + if (sofia_test_pflag(profile, PFLAG_SQL_IN_TRANS)) { /* Do we have enough statements or is the timeout expired */ while (sql || (sofia_test_pflag(profile, PFLAG_RUNNING) && mod_sofia_globals.running == 1 && @@ -1745,6 +1820,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void switch_event_t *s_event; int use_100rel = !sofia_test_pflag(profile, PFLAG_DISABLE_100REL); int use_timer = !sofia_test_pflag(profile, PFLAG_DISABLE_TIMER); + int use_rfc_5626 = sofia_test_pflag(profile, PFLAG_ENABLE_RFC5626); const char *supported = NULL; int sanity; switch_thread_t *worker_thread; @@ -1766,7 +1842,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void goto end; } - supported = switch_core_sprintf(profile->pool, "%s%sprecondition, path, replaces", use_100rel ? "100rel, " : "", use_timer ? "timer, " : ""); + supported = switch_core_sprintf(profile->pool, "%s%s%sprecondition, path, replaces", use_100rel ? "100rel, " : "", use_timer ? "timer, " : "", use_rfc_5626 ? "outbound, " : ""); if (sofia_test_pflag(profile, PFLAG_AUTO_NAT) && switch_nat_get_type()) { if (switch_nat_add_mapping(profile->sip_port, SWITCH_NAT_UDP, NULL, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) { @@ -1971,7 +2047,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void nua_shutdown(profile->nua); sanity = 10; - while (!sofia_test_pflag(profile, PFLAG_SHUTDOWN)) { + while (!sofia_test_pflag(profile, PFLAG_SHUTDOWN) || profile->queued_events > 0) { su_root_step(profile->s_root, 1000); if (!--sanity) { break; @@ -2231,7 +2307,7 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) if ((gateway = switch_core_alloc(profile->pool, sizeof(*gateway)))) { const char *sipip, *format; switch_uuid_t uuid; - uint32_t ping_freq = 0, extension_in_contact = 0, distinct_to = 0; + uint32_t ping_freq = 0, extension_in_contact = 0, distinct_to = 0, rfc_5626 = 0; int ping_max = 1, ping_min = -1; char *register_str = "true", *scheme = "Digest", *realm = NULL, @@ -2246,7 +2322,8 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) *retry_seconds = "30", *timeout_seconds = "60", *from_user = "", *from_domain = NULL, *outbound_proxy = NULL, *register_proxy = NULL, *contact_host = NULL, - *contact_params = NULL, *params = NULL, *register_transport = NULL; + *contact_params = NULL, *params = NULL, *register_transport = NULL, + *reg_id = NULL, *str_rfc_5626 = NULL; if (!context) { context = "default"; @@ -2369,6 +2446,10 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) outbound_proxy = val; } else if (!strcmp(var, "distinct-to")) { distinct_to = switch_true(val); + } else if (!strcmp(var, "rfc-5626")) { + rfc_5626 = switch_true(val); + } else if (!strcmp(var, "reg-id")) { + reg_id = val; } else if (!strcmp(var, "contact-params")) { contact_params = val; } else if (!strcmp(var, "register-transport")) { @@ -2382,6 +2463,17 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) gateway->register_transport = transport; } } +#ifndef WIN32 + /* Windows todo figure this out! */ + /* RFC 5626 enable in the GW profile and the UA profile */ + if (rfc_5626 && sofia_test_pflag(profile, PFLAG_ENABLE_RFC5626)) { + char str_guid[su_guid_strlen + 1]; + su_guid_t guid[1]; + su_guid_generate(guid); + su_guid_sprintf(str_guid, su_guid_strlen + 1, guid); + str_rfc_5626 = switch_core_sprintf(gateway->pool, ";reg-id=%s;+sip.instance=\"\"",reg_id,str_guid); + } +#endif if (ping_freq) { if (ping_freq >= 5) { @@ -2406,14 +2498,16 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) } } - if (zstr(username)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: username param is REQUIRED!\n"); - goto skip; - } + if (switch_true(register_str)) { + if (zstr(username)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: username param is REQUIRED!\n"); + goto skip; + } - if (zstr(password)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: password param is REQUIRED!\n"); - goto skip; + if (zstr(password)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: password param is REQUIRED!\n"); + goto skip; + } } if (zstr(from_user)) { @@ -2546,17 +2640,36 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) } if (extension_in_contact) { - format = strchr(sipip, ':') ? "" : ""; - gateway->register_contact = switch_core_sprintf(gateway->pool, format, extension, - sipip, - sofia_glue_transport_has_tls(gateway->register_transport) ? - profile->tls_sip_port : profile->sip_port, params); + if (rfc_5626) { + format = strchr(sipip, ':') ? "%s" : "%s"; + gateway->register_contact = switch_core_sprintf(gateway->pool, format, extension, + sipip, + sofia_glue_transport_has_tls(gateway->register_transport) ? + profile->tls_sip_port : profile->sip_port, params, str_rfc_5626); + + } else { + format = strchr(sipip, ':') ? "" : ""; + gateway->register_contact = switch_core_sprintf(gateway->pool, format, extension, + sipip, + sofia_glue_transport_has_tls(gateway->register_transport) ? + profile->tls_sip_port : profile->sip_port, params,contact_params); + } } else { - format = strchr(sipip, ':') ? "" : ""; - gateway->register_contact = switch_core_sprintf(gateway->pool, format, gateway->name, - sipip, - sofia_glue_transport_has_tls(gateway->register_transport) ? - profile->tls_sip_port : profile->sip_port, params); + if (rfc_5626) { + format = strchr(sipip, ':') ? "%s" : "%s"; + gateway->register_contact = switch_core_sprintf(gateway->pool, format, gateway->name, + sipip, + sofia_glue_transport_has_tls(gateway->register_transport) ? + profile->tls_sip_port : profile->sip_port, params, str_rfc_5626); + + } else { + format = strchr(sipip, ':') ? "" : ""; + gateway->register_contact = switch_core_sprintf(gateway->pool, format, gateway->name, + sipip, + sofia_glue_transport_has_tls(gateway->register_transport) ? + profile->tls_sip_port : profile->sip_port, params); + + } } gateway->expires_str = switch_core_strdup(gateway->pool, expire_seconds); @@ -2766,6 +2879,7 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile) /* you could change profile->foo here if it was a minor change like context or dialplan ... */ profile->acl_count = 0; + profile->nat_acl_count = 0; profile->reg_acl_count = 0; profile->proxy_acl_count = 0; sofia_set_pflag(profile, PFLAG_STUN_ENABLED); @@ -2861,6 +2975,18 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile) } else { sofia_clear_pflag(profile, PFLAG_LOG_AUTH_FAIL); } + } else if (!strcasecmp(var, "presence-proto-lookup")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_PRESENCE_MAP); + } else { + sofia_clear_pflag(profile, PFLAG_PRESENCE_MAP); + } + } else if (!strcasecmp(var, "profile-standby")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_STANDBY); + } else { + sofia_clear_pflag(profile, PFLAG_STANDBY); + } } else if (!strcasecmp(var, "liberal-dtmf")) { if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_LIBERAL_DTMF); @@ -3079,6 +3205,8 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile) profile->user_agent_filter = switch_core_strdup(profile->pool, val); } else if (!strcasecmp(var, "max-registrations-per-extension")) { profile->max_registrations_perext = atoi(val); + } else if (!strcasecmp(var,"presence-privacy")) { + profile->presence_privacy = switch_core_strdup(profile->pool, val); } else if (!strcasecmp(var, "rfc2833-pt")) { profile->te = (switch_payload_t) atoi(val); } else if (!strcasecmp(var, "cng-pt") && !(sofia_test_pflag(profile, PFLAG_SUPPRESS_CNG))) { @@ -3292,6 +3420,12 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile) profile->timer_t4 = 4000; } nua_set_params(profile->nua, NTATAG_SIP_T4(profile->timer_t4), TAG_END()); + } else if (!strcasecmp(var, "sip-options-respond-503-on-busy")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY); + } else { + sofia_clear_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY); + } } } } @@ -3524,8 +3658,9 @@ switch_status_t config_sofia(int reload, char *profile_name) profile->contact_user = SOFIA_DEFAULT_CONTACT_USER; sofia_set_pflag(profile, PFLAG_PASS_CALLEE_ID); sofia_set_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER); + sofia_set_pflag(profile, PFLAG_PRESENCE_ON_FIRST_REGISTER); sofia_set_pflag(profile, PFLAG_SQL_IN_TRANS); - sofia_set_pflag(profile, PFLAG_PRESENCE_ON_REGISTER); + profile->shutdown_type = "false"; profile->local_network = "localnet.auto"; sofia_set_flag(profile, TFLAG_ENABLE_SOA); @@ -3576,6 +3711,18 @@ switch_status_t config_sofia(int reload, char *profile_name) } else { sofia_clear_pflag(profile, PFLAG_LOG_AUTH_FAIL); } + } else if (!strcasecmp(var, "presence-proto-lookup")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_PRESENCE_MAP); + } else { + sofia_clear_pflag(profile, PFLAG_PRESENCE_MAP); + } + } else if (!strcasecmp(var, "profile-standby")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_STANDBY); + } else { + sofia_clear_pflag(profile, PFLAG_STANDBY); + } } else if (!strcasecmp(var, "liberal-dtmf")) { if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_LIBERAL_DTMF); @@ -3632,7 +3779,7 @@ switch_status_t config_sofia(int reload, char *profile_name) sofia_clear_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER); } } else if (!strcasecmp(var, "send-presence-on-register")) { - if (switch_true(val)) { + if (switch_true(val) || !strcasecmp(val, "all")) { sofia_set_pflag(profile, PFLAG_PRESENCE_ON_REGISTER); } else if (!strcasecmp(val, "first-only")) { sofia_clear_pflag(profile, PFLAG_PRESENCE_ON_REGISTER); @@ -3968,6 +4115,10 @@ switch_status_t config_sofia(int reload, char *profile_name) } else if (switch_true(val)) { profile->pres_type = PRES_TYPE_FULL; } + } else if (!strcasecmp(var, "presence-privacy")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_PRESENCE_PRIVACY); + } } else if (!strcasecmp(var, "manage-shared-appearance")) { if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE); @@ -3975,8 +4126,9 @@ switch_status_t config_sofia(int reload, char *profile_name) sofia_set_pflag(profile, PFLAG_MULTIREG); } else if (!strcasecmp(val, "sylantro")) { - profile->sla_contact = switch_core_sprintf(profile->pool, "sla-agent"); - sofia_set_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE_SYLANTRO); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, + "Sylantro support has been removed.\n" + "It was incomplete anyway, and we fully support the broadsoft SCA shared line spec."); } } else if (!strcasecmp(var, "disable-srv")) { if (switch_true(val)) { @@ -4125,6 +4277,10 @@ switch_status_t config_sofia(int reload, char *profile_name) if (!switch_true(val)) { sofia_set_pflag(profile, PFLAG_DISABLE_TIMER); } + } else if (!strcasecmp(var, "enable-rfc-5626")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_ENABLE_RFC5626); + } } else if (!strcasecmp(var, "minimum-session-expires")) { profile->minimum_session_expires = atoi(val); /* per RFC 4028: minimum_session_expires must be > 90 */ @@ -4288,6 +4444,12 @@ switch_status_t config_sofia(int reload, char *profile_name) } else { profile->timer_t4 = 4000; } + } else if (!strcasecmp(var, "sip-options-respond-503-on-busy")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY); + } else { + sofia_clear_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY); + } } else if (!strcasecmp(var, "reuse-connections")) { switch_bool_t value = switch_true(val); if (!value) { @@ -4510,6 +4672,14 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status switch_caller_profile_t *caller_profile = NULL; int has_t38 = 0; + switch_channel_clear_flag(channel, CF_REQ_MEDIA); + + if (status >= 900) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s status %d received.\n", + switch_channel_get_name(channel), status); + return; + } + sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port); switch_channel_set_variable_printf(channel, "sip_local_network_addr", "%s", profile->extsipip ? profile->extsipip : profile->sipip); @@ -4523,8 +4693,6 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status caller_profile->network_addr = switch_core_strdup(caller_profile->pool, network_ip); } - switch_channel_clear_flag(channel, CF_REQ_MEDIA); - tech_pvt->last_sdp_str = NULL; if (!sofia_use_soa(tech_pvt) && sip->sip_payload && sip->sip_payload->pl_data) { tech_pvt->last_sdp_str = switch_core_session_strdup(session, sip->sip_payload->pl_data); @@ -4609,9 +4777,9 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status const char *vval; if (status > 199) { - sofia_glue_set_extra_headers(channel, sip, SOFIA_SIP_RESPONSE_HEADER_PREFIX); + sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_RESPONSE_HEADER_PREFIX); } else { - sofia_glue_set_extra_headers(channel, sip, SOFIA_SIP_PROGRESS_HEADER_PREFIX); + sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_PROGRESS_HEADER_PREFIX); } @@ -4814,10 +4982,15 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status } - if (sip->sip_payload && sip->sip_payload->pl_data && switch_stristr("m=image", sip->sip_payload->pl_data)) { + if (!switch_channel_test_flag(channel, CF_PROXY_MODE) && + sip->sip_payload && sip->sip_payload->pl_data && switch_stristr("m=image", sip->sip_payload->pl_data)) { has_t38 = 1; } + if (switch_channel_test_flag(channel, CF_PROXY_MODE)) { + sofia_clear_flag(tech_pvt, TFLAG_T38_PASSTHRU); + } + if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA) || (sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && (has_t38 || status > 299))) { @@ -4835,9 +5008,9 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status sip->sip_content_type && sip->sip_content_type->c_subtype && switch_stristr("sdp", sip->sip_content_type->c_subtype)) { tech_pvt->remote_sdp_str = switch_core_session_strdup(tech_pvt->session, sip->sip_payload->pl_data); r_sdp = tech_pvt->remote_sdp_str; - sofia_glue_tech_proxy_remote_addr(tech_pvt); + sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL); } - + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing %d %s to other leg\n", status, phrase); if (status > 299) { @@ -4950,6 +5123,8 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status !switch_channel_test_flag(channel, CF_RING_READY)) { const char *from_user = "", *from_host = "", *to_user = "", *to_host = "", *contact_user = "", *contact_host = ""; const char *user_agent = "", *call_id = ""; + const char *to_tag = ""; + const char *from_tag = ""; char *sql = NULL; if (sip->sip_user_agent) { @@ -4962,12 +5137,14 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status if (to) { from_user = switch_str_nil(to->url_user); + from_tag = switch_str_nil(sip->sip_to->a_tag); } if (from) { from_host = switch_str_nil(from->url_host); to_user = switch_str_nil(from->url_user); to_host = switch_str_nil(from->url_host); + to_tag = switch_str_nil(sip->sip_from->a_tag); } if (contact) { @@ -4980,7 +5157,8 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status const char *presence_id = switch_channel_get_variable(channel, "presence_id"); char *full_contact = ""; char *p = NULL; - + time_t now; + if (sip->sip_contact) { full_contact = sip_header_as_string(nua_handle_home(tech_pvt->nh), (void *) sip->sip_contact); } @@ -4988,16 +5166,19 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status if (call_info && (p = strchr(call_info, ';'))) { p++; } + + now = switch_epoch_time_now(NULL); + sql = switch_mprintf("insert into sip_dialogs " - "(call_id,uuid,sip_to_user,sip_to_host,sip_from_user,sip_from_host,contact_user," - "contact_host,state,direction,user_agent,profile_name,hostname,contact,presence_id,presence_data,call_info) " - "values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q')", + "(call_id,uuid,sip_to_user,sip_to_host,sip_to_tag,sip_from_user,sip_from_host,sip_from_tag,contact_user," + "contact_host,state,direction,user_agent,profile_name,hostname,contact,presence_id,presence_data,call_info,rcd) " + "values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld)", call_id, switch_core_session_get_uuid(session), - to_user, to_host, from_user, from_host, contact_user, + to_user, to_host, to_tag, from_user, from_host, from_tag, contact_user, contact_host, astate, "outbound", user_agent, profile->name, mod_sofia_globals.hostname, switch_str_nil(full_contact), - switch_str_nil(presence_id), switch_str_nil(presence_data), switch_str_nil(p)); + switch_str_nil(presence_id), switch_str_nil(presence_data), switch_str_nil(p), (long) now); switch_assert(sql); sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); @@ -5080,6 +5261,83 @@ static void launch_media_on_hold(switch_core_session_t *session) switch_thread_create(&thread, thd_attr, media_on_hold_thread_run, session, switch_core_session_get_pool(session)); } +static void mark_transfer_record(switch_core_session_t *session, const char *br_a, const char *br_b) +{ + switch_core_session_t *br_b_session, *br_a_session; + switch_channel_t *channel; + const char *uvar1, *dvar1, *uvar2, *dvar2; + + channel = switch_core_session_get_channel(session); + + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { + uvar1 = "sip_from_user"; + dvar1 = "sip_from_host"; + } else { + uvar1 = "sip_to_user"; + dvar1 = "sip_to_host"; + } + + + if ((br_b_session = switch_core_session_locate(br_b)) ) { + switch_channel_t *br_b_channel = switch_core_session_get_channel(br_b_session); + switch_caller_profile_t *cp = switch_channel_get_caller_profile(br_b_channel); + + if (switch_channel_direction(br_b_channel) == SWITCH_CALL_DIRECTION_INBOUND) { + uvar2 = "sip_from_user"; + dvar2 = "sip_from_host"; + } else { + uvar2 = "sip_to_user"; + dvar2 = "sip_to_host"; + } + + cp->transfer_source = switch_core_sprintf(cp->pool, + "%ld:%s:att_xfer:%s@%s/%s@%s", + (long) switch_epoch_time_now(NULL), + cp->uuid_str, + switch_channel_get_variable(channel, uvar1), + switch_channel_get_variable(channel, dvar1), + switch_channel_get_variable(br_b_channel, uvar2), + switch_channel_get_variable(br_b_channel, dvar2)); + + switch_channel_add_variable_var_check(br_b_channel, SWITCH_TRANSFER_HISTORY_VARIABLE, cp->transfer_source, SWITCH_FALSE, SWITCH_STACK_PUSH); + switch_channel_set_variable(br_b_channel, SWITCH_TRANSFER_SOURCE_VARIABLE, cp->transfer_source); + + switch_core_session_rwunlock(br_b_session); + } + + + + if ((br_a_session = switch_core_session_locate(br_a)) ) { + switch_channel_t *br_a_channel = switch_core_session_get_channel(br_a_session); + switch_caller_profile_t *cp = switch_channel_get_caller_profile(br_a_channel); + + if (switch_channel_direction(br_a_channel) == SWITCH_CALL_DIRECTION_INBOUND) { + uvar2 = "sip_from_user"; + dvar2 = "sip_from_host"; + } else { + uvar2 = "sip_to_user"; + dvar2 = "sip_to_host"; + } + + cp->transfer_source = switch_core_sprintf(cp->pool, + "%ld:%s:att_xfer:%s@%s/%s@%s", + (long) switch_epoch_time_now(NULL), + cp->uuid_str, + switch_channel_get_variable(channel, uvar1), + switch_channel_get_variable(channel, dvar1), + switch_channel_get_variable(br_a_channel, uvar2), + switch_channel_get_variable(br_a_channel, dvar2)); + + switch_channel_add_variable_var_check(br_a_channel, SWITCH_TRANSFER_HISTORY_VARIABLE, cp->transfer_source, SWITCH_FALSE, SWITCH_STACK_PUSH); + switch_channel_set_variable(br_a_channel, SWITCH_TRANSFER_SOURCE_VARIABLE, cp->transfer_source); + + switch_core_session_rwunlock(br_a_session); + } + + +} + + static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, char const *phrase, nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip, @@ -5212,6 +5470,19 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, status = 183; } + if (channel && profile->pres_type && ss_state == nua_callstate_ready && status == 200) { + const char* to_tag = ""; + char *sql = NULL; + to_tag = switch_str_nil(switch_channel_get_variable(channel, "sip_to_tag")); + sql = switch_mprintf("update sip_dialogs set sip_to_tag='%q' " + "where uuid='%q' and sip_to_tag = ''", to_tag, switch_core_session_get_uuid(session)); + + if (mod_sofia_globals.debug_presence > 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "QUERY SQL %s\n", sql); + } + sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); + } + if (channel && (status == 180 || status == 183) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { const char *val; if ((val = switch_channel_get_variable(channel, "sip_auto_answer")) && switch_true(val)) { @@ -5401,15 +5672,17 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, const char *br_b = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE); char *br_a = b_private->uuid; + if (br_b) { - switch_core_session_t *tmp; - - if (switch_true(switch_channel_get_variable(channel, "recording_follow_transfer")) && + switch_core_session_t *tmp; + + if (switch_true(switch_channel_get_variable(channel, "recording_follow_transfer")) && (tmp = switch_core_session_locate(br_a))) { switch_core_media_bug_transfer_recordings(session, tmp); switch_core_session_rwunlock(tmp); } + mark_transfer_record(session, br_a, br_b); switch_ivr_uuid_bridge(br_a, br_b); switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER"); sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD); @@ -5582,6 +5855,15 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, goto done; } + if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { + if (sofia_glue_tech_proxy_remote_addr(tech_pvt, r_sdp) == SWITCH_STATUS_SUCCESS) { + nua_respond(tech_pvt->nh, SIP_200_OK, TAG_END()); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params changed, NOT proxying re-invite.\n"); + switch_core_session_rwunlock(other_session); + goto done; + } + } + msg = switch_core_session_alloc(other_session, sizeof(*msg)); msg->message_id = SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT; msg->from = __FILE__; @@ -5902,12 +6184,11 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, switch_snprintf(st, sizeof(st), "%d", status); switch_channel_set_variable(channel, "sip_term_status", st); switch_snprintf(st, sizeof(st), "sip:%d", status); - switch_channel_set_variable_partner(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, st); switch_channel_set_variable(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, st); if (phrase) { switch_channel_set_variable_partner(channel, "sip_hangup_phrase", phrase); } - sofia_glue_set_extra_headers(channel, sip, SOFIA_SIP_BYE_HEADER_PREFIX); + sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_BYE_HEADER_PREFIX); } switch_snprintf(st, sizeof(st), "%d", cause); switch_channel_set_variable(channel, "sip_term_cause", st); @@ -5973,12 +6254,13 @@ void *SWITCH_THREAD_FUNC nightmare_xfer_thread_run(switch_thread_t *thread, void if ((status = switch_ivr_originate(NULL, &tsession, &cause, nhelper->exten_with_params, timeout, NULL, NULL, NULL, switch_channel_get_caller_profile(channel_a), nhelper->vars, SOF_NONE, NULL)) == SWITCH_STATUS_SUCCESS) { if (switch_channel_up(channel_a)) { - + if (switch_true(switch_channel_get_variable(channel_a, "recording_follow_transfer"))) { switch_core_media_bug_transfer_recordings(session, a_session); } tuuid_str = switch_core_session_get_uuid(tsession); + mark_transfer_record(session, nhelper->bridge_to_uuid, tuuid_str); switch_ivr_uuid_bridge(nhelper->bridge_to_uuid, tuuid_str); switch_channel_set_variable(channel_a, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER"); sofia_set_flag_locked(tech_pvt, TFLAG_BYE); @@ -6342,6 +6624,8 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t switch_core_session_rwunlock(tmp); } + + mark_transfer_record(session, br_b, br_a); switch_ivr_uuid_bridge(br_b, br_a); switch_channel_set_variable(channel_b, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER"); @@ -6739,9 +7023,44 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t if (session) { /* Get the channel */ switch_channel_t *channel = switch_core_session_get_channel(session); + const char *vval; /* Barf if we didn't get our private */ assert(switch_core_session_get_private(session)); + + sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_INFO_HEADER_PREFIX); + + + + if (sip && sip->sip_content_type && sip->sip_content_type->c_type && !strcasecmp(sip->sip_content_type->c_type, "freeswitch/data")) { + char *data = NULL; + + if (sip->sip_payload && sip->sip_payload->pl_data) { + data = sip->sip_payload->pl_data; + } + + if ((vval = switch_channel_get_variable(channel, "sip_copy_custom_headers")) && switch_true(vval)) { + switch_core_session_t *nsession = NULL; + + switch_core_session_get_partner(session, &nsession); + + if (nsession) { + switch_core_session_message_t *msg; + + switch_ivr_transfer_variable(session, nsession, SOFIA_SIP_INFO_HEADER_PREFIX_T); + msg = switch_core_session_alloc(nsession, sizeof(*msg)); + MESSAGE_STAMP_FFL(msg); + msg->message_id = SWITCH_MESSAGE_INDICATE_INFO; + + msg->string_array_arg[2] = switch_core_session_strdup(nsession, data); + + msg->from = __FILE__; + switch_core_session_queue_message(nsession, msg); + + switch_core_session_rwunlock(nsession); + } + } + } if (sip && sip->sip_content_type && sip->sip_content_type->c_subtype && sip->sip_content_type->c_type && !strncasecmp(sip->sip_content_type->c_type, "message", 7) && @@ -7229,7 +7548,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ transport = sofia_glue_url2transport(sip->sip_contact->m_url); - tech_pvt->record_route = + tech_pvt->record_route= switch_core_session_sprintf(session, "sip:%s@%s%s%s:%d;transport=%s", sip->sip_contact->m_url->url_user, @@ -7276,16 +7595,12 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ } if (sip->sip_from && sip->sip_from->a_url) { - char *tmp; from_user = sip->sip_from->a_url->url_user; from_host = sip->sip_from->a_url->url_host; channel_name = url_set_chanvars(session, sip->sip_from->a_url, sip_from); - if (sip->sip_from->a_url->url_params && (tmp = sofia_glue_find_parameter(sip->sip_from->a_url->url_params, "isup-oli="))) { - aniii = switch_core_session_strdup(session, tmp + 9); - if ((tmp = strchr(aniii, ';'))) { - tmp = '\0'; - } + if (sip->sip_from->a_url->url_params) { + aniii = switch_find_parameter(sip->sip_from->a_url->url_params, "isup-oli", switch_core_session_get_pool(session)); } if (!zstr(from_user)) { @@ -7627,7 +7942,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ if (sip->sip_request->rq_url->url_params) { - gw_param_name = sofia_glue_find_parameter_value(session, sip->sip_request->rq_url->url_params, "gw="); + gw_param_name = switch_find_parameter(sip->sip_request->rq_url->url_params, "gw", switch_core_session_get_pool(session)); } if (strstr(destination_number, "gw+")) { @@ -7971,6 +8286,8 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ const char *dialog_from_user = "", *dialog_from_host = "", *to_user = "", *to_host = "", *contact_user = "", *contact_host = ""; const char *user_agent = "", *call_id = ""; url_t *from = NULL, *to = NULL, *contact = NULL; + const char *to_tag = ""; + const char *from_tag = ""; char *sql = NULL; if (sip->sip_to) { @@ -7994,11 +8311,13 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ if (to) { to_user = switch_str_nil(to->url_user); to_host = switch_str_nil(to->url_host); + to_tag = switch_str_nil(sip->sip_to->a_tag); } if (from) { dialog_from_user = switch_str_nil(from->url_user); dialog_from_host = switch_str_nil(from->url_host); + from_tag = switch_str_nil(sip->sip_from->a_tag); } if (contact) { @@ -8011,7 +8330,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ const char *presence_id = switch_channel_get_variable(channel, "presence_id"); char *full_contact = ""; char *p = NULL; - + time_t now; if (sip->sip_contact) { full_contact = sip_header_as_string(nua_handle_home(tech_pvt->nh), (void *) sip->sip_contact); @@ -8025,17 +8344,18 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ } } + now = switch_epoch_time_now(NULL); sql = switch_mprintf("insert into sip_dialogs " - "(call_id,uuid,sip_to_user,sip_to_host,sip_from_user,sip_from_host,contact_user," - "contact_host,state,direction,user_agent,profile_name,hostname,contact,presence_id,presence_data,call_info) " - "values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q')", + "(call_id,uuid,sip_to_user,sip_to_host,sip_to_tag,sip_from_user,sip_from_host,sip_from_tag,contact_user," + "contact_host,state,direction,user_agent,profile_name,hostname,contact,presence_id,presence_data,call_info,rcd) " + "values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld)", call_id, tech_pvt->sofia_private->uuid, - to_user, to_host, dialog_from_user, dialog_from_host, + to_user, to_host, to_tag, dialog_from_user, dialog_from_host, from_tag, contact_user, contact_host, "confirmed", "inbound", user_agent, profile->name, mod_sofia_globals.hostname, switch_str_nil(full_contact), - switch_str_nil(presence_id), switch_str_nil(presence_data), switch_str_nil(p)); + switch_str_nil(presence_id), switch_str_nil(presence_data), switch_str_nil(p), now); switch_assert(sql); @@ -8088,7 +8408,16 @@ void sofia_handle_sip_i_options(int status, sofia_dispatch_event_t *de, tagi_t tags[]) { - nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END()); + uint32_t sess_count = switch_core_session_count(); + uint32_t sess_max = switch_core_session_limit(0); + + if (sofia_test_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY) && + (sess_count >= sess_max || !sofia_test_pflag(profile, PFLAG_RUNNING) || !switch_core_ready_inbound())) { + nua_respond(nh, 503, "Maximum Calls In Progress", NUTAG_WITH_THIS_MSG(de->data->e_msg), SIPTAG_RETRY_AFTER_STR("300"), TAG_END()); + } else { + nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END()); + } + } void sofia_info_send_sipfrag(switch_core_session_t *aleg, switch_core_session_t *bleg) @@ -8119,6 +8448,7 @@ void sofia_info_send_sipfrag(switch_core_session_t *aleg, switch_core_session_t if (zstr(acp->caller_id_name)) { snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <%s>", acp->caller_id_number, acp->caller_id_number); } else { + check_decode(acp->caller_id_name, aleg); snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <%s>", acp->caller_id_name, acp->caller_id_number); } diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 518f1065b8..8ea0322657 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -1374,7 +1374,7 @@ char *sofia_overcome_sip_uri_weakness(switch_core_session_t *session, const char } #define RA_PTR_LEN 512 -switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt) +switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt, const char *sdp_str) { const char *err; char rip[RA_PTR_LEN] = ""; @@ -1383,29 +1383,34 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt) char *p, *ip_ptr = NULL, *port_ptr = NULL, *vid_port_ptr = NULL, *pe; int x; const char *val; - - if (zstr(tech_pvt->remote_sdp_str)) { - return SWITCH_STATUS_FALSE; + switch_status_t status = SWITCH_STATUS_FALSE; + + if (zstr(sdp_str)) { + sdp_str = tech_pvt->remote_sdp_str; } - if ((p = (char *) switch_stristr("c=IN IP4 ", tech_pvt->remote_sdp_str)) || (p = (char *) switch_stristr("c=IN IP6 ", tech_pvt->remote_sdp_str))) { + if (zstr(sdp_str)) { + goto end; + } + + if ((p = (char *) switch_stristr("c=IN IP4 ", sdp_str)) || (p = (char *) switch_stristr("c=IN IP6 ", sdp_str))) { ip_ptr = p + 9; } - if ((p = (char *) switch_stristr("m=audio ", tech_pvt->remote_sdp_str))) { + if ((p = (char *) switch_stristr("m=audio ", sdp_str))) { port_ptr = p + 8; } - if ((p = (char *) switch_stristr("m=image ", tech_pvt->remote_sdp_str))) { + if ((p = (char *) switch_stristr("m=image ", sdp_str))) { port_ptr = p + 8; } - if ((p = (char *) switch_stristr("m=video ", tech_pvt->remote_sdp_str))) { + if ((p = (char *) switch_stristr("m=video ", sdp_str))) { vid_port_ptr = p + 8; } if (!(ip_ptr && port_ptr)) { - return SWITCH_STATUS_FALSE; + goto end; } p = ip_ptr; @@ -1415,7 +1420,7 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt) rip[x++] = *p; p++; if (p >= pe) { - return SWITCH_STATUS_FALSE; + goto end; } } @@ -1425,7 +1430,7 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt) rp[x++] = *p; p++; if (p >= pe) { - return SWITCH_STATUS_FALSE; + goto end; } } @@ -1435,13 +1440,13 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt) rvp[x++] = *p; p++; if (p >= pe) { - return SWITCH_STATUS_FALSE; + goto end; } } if (!(*rip && *rp)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "invalid SDP\n"); - return SWITCH_STATUS_FALSE; + goto end; } tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, rip); @@ -1496,7 +1501,7 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt) if (remote_host && remote_port && !strcmp(remote_host, tech_pvt->remote_sdp_audio_ip) && remote_port == tech_pvt->remote_sdp_audio_port) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Remote address:port [%s:%d] has not changed.\n", tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port); - return SWITCH_STATUS_SUCCESS; + switch_goto_status(SWITCH_STATUS_BREAK, end); } if ((rport = switch_channel_get_variable(tech_pvt->channel, "sip_remote_audio_rtcp_port"))) { @@ -1507,6 +1512,7 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt) if (switch_rtp_set_remote_address(tech_pvt->rtp_session, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err); + status = SWITCH_STATUS_GENERR; } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n", tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port); @@ -1518,10 +1524,13 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt) if (sofia_test_pflag(tech_pvt->profile, PFLAG_AUTOFIX_TIMING)) { tech_pvt->check_frames = 0; } + status = SWITCH_STATUS_SUCCESS; } } - return SWITCH_STATUS_SUCCESS; + end: + + return status; } @@ -1899,11 +1908,14 @@ char *sofia_glue_get_extra_headers(switch_channel_t *channel, const char *prefix return extra_headers; } -void sofia_glue_set_extra_headers(switch_channel_t *channel, sip_t const *sip, const char *prefix) +void sofia_glue_set_extra_headers(switch_core_session_t *session, sip_t const *sip, const char *prefix) { sip_unknown_t *un; char name[512] = ""; + switch_channel_t *channel = switch_core_session_get_channel(session); + char *pstr; + if (!sip || !channel) { return; } @@ -1916,6 +1928,13 @@ void sofia_glue_set_extra_headers(switch_channel_t *channel, sip_t const *sip, c } } } + + pstr = switch_core_session_sprintf(session, "execute_on_%sprefix", prefix); + switch_channel_execute_on(channel, pstr); + switch_channel_api_on(channel, pstr); + + switch_channel_execute_on(channel, "execute_on_sip_extra_headers"); + switch_channel_api_on(channel, "api_on_sip_extra_headers"); } @@ -1941,7 +1960,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) sofia_destination_t *dst = NULL; sofia_cid_type_t cid_type = tech_pvt->profile->cid_type; sip_cseq_t *cseq = NULL; - const char *invite_full_via = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_via"); + const char *invite_record_route = switch_channel_get_variable(tech_pvt->channel, "sip_invite_record_route"); const char *invite_route_uri = switch_channel_get_variable(tech_pvt->channel, "sip_invite_route_uri"); const char *invite_full_from = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_from"); const char *invite_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_to"); @@ -1950,6 +1969,23 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) const char *force_full_from = switch_channel_get_variable(tech_pvt->channel, "sip_force_full_from"); const char *force_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_force_full_to"); char *mp = NULL, *mp_type = NULL; + char *record_route = NULL; + const char *recover_via = NULL; + + if (sofia_test_flag(tech_pvt, TFLAG_RECOVERING)) { + const char *recover_contact = switch_channel_get_variable(tech_pvt->channel, "sip_recover_contact"); + recover_via = switch_channel_get_variable(tech_pvt->channel, "sip_recover_via"); + + if (!zstr(invite_record_route)) { + record_route = switch_core_session_sprintf(session, "Record-Route: %s", invite_record_route); + } + + if (recover_contact) { + char *tmp = switch_core_session_strdup(session, recover_contact); + tech_pvt->redirected = sofia_glue_get_url_from_contact(tmp, 0); + } + } + rep = switch_channel_get_variable(channel, SOFIA_REPLACES_HEADER); @@ -1959,6 +1995,12 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) caller_profile = switch_channel_get_caller_profile(channel); + if (!caller_profile) { + switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + return SWITCH_STATUS_FALSE; + } + + cid_name = caller_profile->caller_id_name; cid_num = caller_profile->caller_id_number; sofia_glue_tech_prepare_codecs(tech_pvt); @@ -2051,7 +2093,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) if (!zstr(tech_pvt->gateway_from_str)) { rpid_domain = switch_core_session_strdup(session, tech_pvt->gateway_from_str); } else if (!zstr(tech_pvt->from_str)) { - rpid_domain = switch_core_session_strdup(session, tech_pvt->from_str); + rpid_domain = switch_core_session_strdup(session, use_from_str); } sofia_glue_get_url_from_contact(rpid_domain, 0); @@ -2214,10 +2256,14 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) } switch_channel_set_variable(channel, "sip_req_uri", s); } + + switch_channel_set_variable(channel, "sip_to_host", sofia_glue_get_host(to_str, switch_core_session_get_pool(session))); + switch_channel_set_variable(channel, "sip_from_host", sofia_glue_get_host(from_str, switch_core_session_get_pool(session))); if (!(tech_pvt->nh = nua_handle(tech_pvt->profile->nua, NULL, NUTAG_URL(url_str), TAG_IF(call_id, SIPTAG_CALL_ID_STR(call_id)), + TAG_IF(!zstr(record_route), SIPTAG_HEADER_STR(record_route)), SIPTAG_TO_STR(to_str), SIPTAG_FROM_STR(from_str), SIPTAG_CONTACT_STR(invite_contact), TAG_END()))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, @@ -2376,7 +2422,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { if (switch_rtp_ready(tech_pvt->rtp_session)) { - sofia_glue_tech_proxy_remote_addr(tech_pvt); + sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL); } sofia_glue_tech_patch_sdp(tech_pvt); } @@ -2441,7 +2487,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)), TAG_IF(tech_pvt->redirected, NUTAG_URL(tech_pvt->redirected)), TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), - TAG_IF(!zstr(invite_full_via), SIPTAG_VIA_STR(invite_full_via)), + TAG_IF(!zstr(recover_via), SIPTAG_VIA_STR(recover_via)), TAG_IF(!zstr(tech_pvt->rpid), SIPTAG_REMOTE_PARTY_ID_STR(tech_pvt->rpid)), TAG_IF(!zstr(tech_pvt->preferred_id), SIPTAG_P_PREFERRED_IDENTITY_STR(tech_pvt->preferred_id)), TAG_IF(!zstr(tech_pvt->asserted_id), SIPTAG_P_ASSERTED_IDENTITY_STR(tech_pvt->asserted_id)), @@ -2475,7 +2521,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)), TAG_IF(tech_pvt->redirected, NUTAG_URL(tech_pvt->redirected)), TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), - TAG_IF(!zstr(invite_full_via), SIPTAG_VIA_STR(invite_full_via)), + TAG_IF(!zstr(recover_via), SIPTAG_VIA_STR(recover_via)), TAG_IF(!zstr(tech_pvt->rpid), SIPTAG_REMOTE_PARTY_ID_STR(tech_pvt->rpid)), TAG_IF(!zstr(tech_pvt->preferred_id), SIPTAG_P_PREFERRED_IDENTITY_STR(tech_pvt->preferred_id)), TAG_IF(!zstr(tech_pvt->asserted_id), SIPTAG_P_ASSERTED_IDENTITY_STR(tech_pvt->asserted_id)), @@ -3144,9 +3190,7 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f } if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) { - if ((status = sofia_glue_tech_proxy_remote_addr(tech_pvt)) != SWITCH_STATUS_SUCCESS) { - goto end; - } + sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL); if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) && !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) { @@ -3247,7 +3291,7 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f switch_rtp_intentional_bugs(tech_pvt->rtp_session, tech_pvt->rtp_bugs | tech_pvt->profile->manual_rtp_bugs); if ((vad_in && inb) || (vad_out && !inb)) { - switch_rtp_enable_vad(tech_pvt->rtp_session, tech_pvt->session, &tech_pvt->read_codec, SWITCH_VAD_FLAG_TALKING); + switch_rtp_enable_vad(tech_pvt->rtp_session, tech_pvt->session, &tech_pvt->read_codec, SWITCH_VAD_FLAG_TALKING | SWITCH_VAD_FLAG_EVENTS_TALK | SWITCH_VAD_FLAG_EVENTS_NOTALK); sofia_set_flag(tech_pvt, TFLAG_VAD); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "AUDIO RTP Engage VAD for %s ( %s %s )\n", switch_channel_get_name(switch_core_session_get_channel(tech_pvt->session)), vad_in ? "in" : "", vad_out ? "out" : ""); @@ -3318,6 +3362,9 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames)\n", jb_msec, qlen); switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER); + if (!switch_false(switch_channel_get_variable(tech_pvt->channel, "sip_jitter_buffer_plc"))) { + switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER_PLC); + } } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_WARNING, "Error Setting Jitterbuffer to %dms (%d frames)\n", jb_msec, qlen); @@ -3464,9 +3511,7 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f } if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) { - if ((status = sofia_glue_tech_proxy_remote_addr(tech_pvt)) != SWITCH_STATUS_SUCCESS) { - goto end; - } + sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL); if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) && !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) { @@ -4423,26 +4468,33 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s int pass = sofia_test_pflag(tech_pvt->profile, PFLAG_T38_PASSTHRU); if (var) { - pass = switch_true(var); + if (!(pass = switch_true(var))) { + if (!strcasecmp(var, "once")) { + pass = 2; + } + } } - /* can't remember if this is necessary but its causing a bug so i'll leave this comment here to remind me - if (sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU)) { - pass = 0; - } - */ - - if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) || - switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA) || !switch_rtp_ready(tech_pvt->rtp_session)) { + if ((pass == 2 && sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU)) || + !sofia_test_flag(tech_pvt, TFLAG_REINVITE) || + switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) || + switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA) || + !switch_rtp_ready(tech_pvt->rtp_session)) { pass = 0; } if (pass && switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) { private_object_t *other_tech_pvt = switch_core_session_get_private(other_session); + switch_channel_t *other_channel = switch_core_session_get_channel(other_session); switch_core_session_message_t *msg; char *remote_host = switch_rtp_get_remote_host(tech_pvt->rtp_session); switch_port_t remote_port = switch_rtp_get_remote_port(tech_pvt->rtp_session); char tmp[32] = ""; + + if (switch_true(switch_channel_get_variable(tech_pvt->channel, "t38_broken_boolean")) && + switch_true(switch_channel_get_variable(tech_pvt->channel, "t38_pass_broken_boolean"))) { + switch_channel_set_variable(other_channel, "t38_broken_boolean", "true"); + } tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, t38_options->remote_ip); tech_pvt->remote_sdp_audio_port = t38_options->remote_port; @@ -4469,7 +4521,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s } - + sofia_glue_copy_t38_options(t38_options, other_session); @@ -5260,6 +5312,30 @@ void sofia_glue_global_siptrace(switch_bool_t on) } +void sofia_glue_global_standby(switch_bool_t on) +{ + switch_hash_index_t *hi; + const void *var; + void *val; + sofia_profile_t *pptr; + + switch_mutex_lock(mod_sofia_globals.hash_mutex); + if (mod_sofia_globals.profile_hash) { + for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) { + switch_hash_this(hi, &var, NULL, &val); + if ((pptr = (sofia_profile_t *) val)) { + if (on) { + sofia_set_pflag_locked(pptr, PFLAG_STANDBY); + } else { + sofia_clear_pflag_locked(pptr, PFLAG_STANDBY); + } + } + } + } + switch_mutex_unlock(mod_sofia_globals.hash_mutex); + +} + void sofia_glue_global_capture(switch_bool_t on) { switch_hash_index_t *hi; @@ -5355,6 +5431,7 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName switch_channel_t *channel; private_object_t *tech_pvt = NULL; const char *tmp; + const char *rr; xml = switch_xml_parse_str_dynamic(argv[3], SWITCH_TRUE); @@ -5362,7 +5439,7 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName return 0; if (!(session = switch_core_session_request_xml(sofia_endpoint_interface, NULL, xml))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "skipping non-bridged entry\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid cdr data, call not recovered\n"); return 0; } @@ -5395,20 +5472,22 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName } } + rr = switch_channel_get_variable(channel, "sip_invite_record_route"); + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { tech_pvt->dest = switch_core_session_sprintf(session, "sip:%s", switch_channel_get_variable(channel, "sip_req_uri")); - switch_channel_set_variable(channel, "sip_invite_full_via", switch_channel_get_variable(channel, "sip_full_via")); - switch_channel_set_variable(channel, "sip_handle_full_from", switch_channel_get_variable(channel, "sip_full_from")); switch_channel_set_variable(channel, "sip_handle_full_to", switch_channel_get_variable(channel, "sip_full_to")); } else { - + tech_pvt->redirected = switch_core_session_sprintf(session, "sip:%s", switch_channel_get_variable(channel, "sip_contact_uri")); - switch_channel_set_variable_printf(channel, "sip_invite_route_uri", "", - switch_channel_get_variable(channel, "sip_from_user"), - switch_channel_get_variable(channel, "sip_network_ip"), switch_channel_get_variable(channel, "sip_network_port") - ); + if (zstr(rr)) { + switch_channel_set_variable_printf(channel, "sip_invite_route_uri", "", + switch_channel_get_variable(channel, "sip_from_user"), + switch_channel_get_variable(channel, "sip_network_ip"), switch_channel_get_variable(channel, "sip_network_port") + ); + } tech_pvt->dest = switch_core_session_sprintf(session, "sip:%s", switch_channel_get_variable(channel, "sip_from_uri")); @@ -5421,6 +5500,10 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName } } + if (rr) { + switch_channel_set_variable(channel, "sip_invite_route_uri", rr); + } + tech_pvt->dest_to = tech_pvt->dest; sofia_glue_attach_private(session, h->profile, tech_pvt, NULL); @@ -5615,6 +5698,8 @@ int sofia_glue_recover(switch_bool_t flush) h.profile = profile; h.total = 0; + sofia_clear_pflag_locked(profile, PFLAG_STANDBY); + if (flush) { sql = switch_mprintf("delete from sip_recovery where profile_name='%q'", profile->name); sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); @@ -5818,7 +5903,10 @@ int sofia_glue_init_sql(sofia_profile_t *profile) " call_info_state VARCHAR(255),\n" " expires INTEGER default 0,\n" " status VARCHAR(255),\n" - " rpid VARCHAR(255)\n" + " rpid VARCHAR(255),\n" + " sip_to_tag VARCHAR(255),\n" + " sip_from_tag VARCHAR(255),\n" + " rcd INTEGER not null default 0\n" ");\n"; char sub_sql[] = @@ -5841,7 +5929,9 @@ int sofia_glue_init_sql(sofia_profile_t *profile) " hostname VARCHAR(255),\n" " network_port VARCHAR(6),\n" " network_ip VARCHAR(255),\n" - " version INTEGER DEFAULT 0 NOT NULL\n" + " version INTEGER DEFAULT 0 NOT NULL,\n" + " orig_proto VARCHAR(255),\n" + " full_to VARCHAR(255)\n" ");\n"; char auth_sql[] = @@ -5881,6 +5971,8 @@ int sofia_glue_init_sql(sofia_profile_t *profile) "create index sr_call_id on sip_registrations (call_id)", "create index sr_sip_user on sip_registrations (sip_user)", "create index sr_sip_host on sip_registrations (sip_host)", + "create index sr_mwi_user on sip_registrations (mwi_user)", + "create index sr_mwi_host on sip_registrations (mwi_host)", "create index sr_profile_name on sip_registrations (profile_name)", "create index sr_presence_hosts on sip_registrations (presence_hosts)", "create index sr_contact on sip_registrations (contact)", @@ -5903,15 +5995,37 @@ int sofia_glue_init_sql(sofia_profile_t *profile) "create index ss_proto on sip_subscriptions (proto)", "create index ss_sub_to_user on sip_subscriptions (sub_to_user)", "create index ss_sub_to_host on sip_subscriptions (sub_to_host)", + "create index ss_expires on sip_subscriptions (expires)", + "create index ss_orig_proto on sip_subscriptions (orig_proto)", + "create index ss_network_port on sip_subscriptions (network_port)", + "create index ss_profile_name on sip_subscriptions (profile_name)", + "create index ss_version on sip_subscriptions (version)", + "create index ss_full_from on sip_subscriptions (full_from)", + "create index ss_contact on sip_subscriptions (contact)", "create index sd_uuid on sip_dialogs (uuid)", "create index sd_hostname on sip_dialogs (hostname)", "create index sd_presence_data on sip_dialogs (presence_data)", "create index sd_call_info on sip_dialogs (call_info)", "create index sd_call_info_state on sip_dialogs (call_info_state)", "create index sd_expires on sip_dialogs (expires)", + "create index sd_rcd on sip_dialogs (rcd)", + "create index sd_sip_to_tag on sip_dialogs (sip_to_tag)", + "create index sd_sip_from_user on sip_dialogs (sip_from_user)", + "create index sd_sip_from_host on sip_dialogs (sip_from_host)", + "create index sd_sip_to_host on sip_dialogs (sip_to_host)", + "create index sd_presence_id on sip_dialogs (presence_id)", + "create index sd_call_id on sip_dialogs (call_id)", + "create index sd_sip_from_tag on sip_dialogs (sip_from_tag)", "create index sp_hostname on sip_presence (hostname)", + "create index sp_open_closed on sip_presence (open_closed)", + "create index sp_sip_user on sip_presence (sip_user)", + "create index sp_sip_host on sip_presence (sip_host)", + "create index sp_profile_name on sip_presence (profile_name)", + "create index sp_expires on sip_presence (expires)", "create index sa_nonce on sip_authentication (nonce)", "create index sa_hostname on sip_authentication (hostname)", + "create index sa_expires on sip_authentication (expires)", + "create index sa_last_nc on sip_authentication (last_nc)", "create index ssa_hostname on sip_shared_appearance_subscriptions (hostname)", "create index ssa_network_ip on sip_shared_appearance_subscriptions (network_ip)", "create index ssa_subscriber on sip_shared_appearance_subscriptions (subscriber)", @@ -5960,13 +6074,13 @@ int sofia_glue_init_sql(sofia_profile_t *profile) free(test_sql); - - test_sql = switch_mprintf("delete from sip_subscriptions where hostname='%q' and version < 0 and network_ip like '%%' and network_port like '%%'", - mod_sofia_globals.hostname); + test_sql = switch_mprintf("delete from sip_subscriptions where hostname='%q' and full_to='XXX'", mod_sofia_globals.hostname); + switch_cache_db_test_reactive(dbh, test_sql, "DROP TABLE sip_subscriptions", sub_sql); free(test_sql); - test_sql = switch_mprintf("delete from sip_dialogs where hostname='%q' and expires <> -9999 or rpid=''", mod_sofia_globals.hostname); + test_sql = switch_mprintf("delete from sip_dialogs where hostname='%q' and (expires <> -9999 or rpid='' or sip_from_tag='' or rcd > 0)", + mod_sofia_globals.hostname); switch_cache_db_test_reactive(dbh, test_sql, "DROP TABLE sip_dialogs", dialog_sql); @@ -6577,6 +6691,14 @@ void sofia_glue_parse_rtp_bugs(switch_rtp_bug_flag_t *flag_pole, const char *str if (switch_stristr("~ACCEPT_ANY_PACKETS", str)) { *flag_pole &= ~RTP_BUG_ACCEPT_ANY_PACKETS; } + + if (switch_stristr("GEN_ONE_GEN_ALL", str)) { + *flag_pole |= RTP_BUG_GEN_ONE_GEN_ALL; + } + + if (switch_stristr("~GEN_ONE_GEN_ALL", str)) { + *flag_pole &= ~RTP_BUG_GEN_ONE_GEN_ALL; + } } char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sofia_dispatch_event_t *de, sofia_nat_parse_t *np) @@ -6703,6 +6825,31 @@ char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sof return contact_str; } +char *sofia_glue_get_host(const char *str, switch_memory_pool_t *pool) +{ + char *s, *p; + + if ((p = strchr(str, '@'))) { + p++; + } else { + return NULL; + } + + if (pool) { + s = switch_core_strdup(pool, p); + } else { + s = strdup(p); + } + + for (p = s; p && *p; p++) { + if ((*p == ';') || (*p == '>')) { + *p = '\0'; + break; + } + } + + return s; +} /* For Emacs: diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 06b1ce496e..99897fb3fd 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -51,11 +51,14 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * static int broadsoft_sla_gather_state_callback(void *pArg, int argc, char **argv, char **columnNames); static int broadsoft_sla_notify_callback(void *pArg, int argc, char **argv, char **columnNames); static void sync_sla(sofia_profile_t *profile, const char *to_user, const char *to_host, switch_bool_t clear, switch_bool_t unseize); +static int sofia_dialog_probe_callback(void *pArg, int argc, char **argv, char **columnNames); +static int sofia_dialog_probe_notify_callback(void *pArg, int argc, char **argv, char **columnNames); struct dialog_helper { char status[512]; char rpid[512]; char presence_id[1024]; + int hits; }; struct resub_helper { @@ -65,6 +68,14 @@ struct resub_helper { int noreg; }; +struct rfc4235_helper { + switch_hash_t *hash; + sofia_profile_t *profile; + switch_memory_pool_t *pool; + switch_event_t *event; + int rowcount; +}; + struct presence_helper { sofia_profile_t *profile; switch_event_t *event; @@ -89,7 +100,7 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event) switch_console_callback_match_node_t *m; char *remote_ip = NULL; char *user_via = NULL; - char *contact_str = NULL; + //char *contact_str = NULL; char *dup_dest = NULL; char *p = NULL; char *remote_host = NULL; @@ -102,9 +113,10 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event) const char *from_full; char header[256] = ""; char *route_uri = NULL; - const char *network_ip = NULL, *network_port = NULL; - + const char *network_ip = NULL, *network_port = NULL, *from_proto; + proto = switch_event_get_header(message_event, "proto"); + from_proto = switch_event_get_header(message_event, "from_proto"); from = switch_event_get_header(message_event, "from"); to = switch_event_get_header(message_event, "to"); //subject = switch_event_get_header(message_event, "subject"); @@ -194,6 +206,7 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event) } else { char *fp, *p = NULL; + fp = strdup(from); switch_assert(fp); @@ -210,9 +223,14 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event) } if (switch_stristr("global", proto)) { - ffrom = switch_mprintf("\"%s\" ", fp, fp, p); + if (!from_proto || !strcasecmp(from_proto, SOFIA_CHAT_PROTO)) { + ffrom = switch_mprintf("\"%s\" ", fp, fp, p); + } else { + ffrom = switch_mprintf("\"%s\" ", fp, from_proto, fp, p); + } + } else { - ffrom = switch_mprintf("\"%s\" ", fp, proto, fp, p); + ffrom = switch_mprintf("\"%s\" ", fp, from_proto ? from_proto : proto, fp, p); } from = ffrom; @@ -255,22 +273,16 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event) //transport_str = sofia_glue_transport2str(transport); switch (transport) { case SOFIA_TRANSPORT_TCP: - contact_str = profile->tcp_public_contact; break; case SOFIA_TRANSPORT_TCP_TLS: - contact_str = profile->tls_public_contact; break; default: - contact_str = profile->public_url; break; } user_via = sofia_glue_create_external_via(NULL, profile, transport); } else { user_via = sofia_glue_create_external_via(NULL, profile, SOFIA_TRANSPORT_UDP); - contact_str = profile->public_url; } - } else { - contact_str = profile->url; } status = SWITCH_STATUS_SUCCESS; @@ -303,7 +315,6 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event) SIPTAG_FROM_STR(from), TAG_IF(contact, NUTAG_URL(contact)), SIPTAG_TO_STR(dup_dest), - SIPTAG_CONTACT_STR(contact_str), TAG_IF(user_via, SIPTAG_VIA_STR(user_via)), SIPTAG_CONTENT_TYPE_STR(ct), @@ -526,14 +537,14 @@ static void actual_sofia_presence_mwi_event_handler(switch_event_t *event) if (for_everyone) { sql = switch_mprintf("select proto,sip_user,sip_host,sub_to_user,sub_to_host,event,contact,call_id,full_from," "full_via,expires,user_agent,accept,profile_name,network_ip" - ",'%q','%q' from sip_subscriptions where version > -1 and expires > -1 and event='message-summary' " - "and sub_to_user='%q' and (sub_to_host='%q' or presence_hosts like '%%%q%%')", stream.data, host, user, host, host); + ",'%q',full_to,network_ip,network_port from sip_subscriptions where version > -1 and expires > -1 and event='message-summary' " + "and sub_to_user='%q' and (sub_to_host='%q' or presence_hosts like '%%%q%%')", stream.data, user, host, host); } else if (sub_call_id) { sql = switch_mprintf("select proto,sip_user,sip_host,sub_to_user,sub_to_host,event,contact,call_id,full_from," "full_via,expires,user_agent,accept,profile_name,network_ip" - ",'%q','%q' from sip_subscriptions where version > -1 and expires > -1 and event='message-summary' " + ",'%q',full_to,network_ip,network_port from sip_subscriptions where version > -1 and expires > -1 and event='message-summary' " "and sub_to_user='%q' and (sub_to_host='%q' or presence_hosts like '%%%q%%' and call_id='%q')", - stream.data, host, user, host, host, sub_call_id); + stream.data, user, host, host, sub_call_id); } @@ -575,11 +586,253 @@ static int sofia_presence_dialog_callback(void *pArg, int argc, char **argv, cha switch_set_string(helper->status, argv[0]); switch_set_string(helper->rpid, argv[1]); switch_set_string(helper->presence_id, argv[2]); + helper->hits++; } return -1; } + +static void do_normal_probe(sofia_profile_t *profile, switch_event_t *event) +{ + char *sql; + struct resub_helper h = { 0 }; + char *to = switch_event_get_header(event, "to"); + char *proto = switch_event_get_header(event, "proto"); + char *probe_user = NULL, *probe_euser, *probe_host, *p; + struct dialog_helper dh = { { 0 } }; + + //DUMP_EVENT(event); + + if (!proto || strcasecmp(proto, SOFIA_CHAT_PROTO) != 0) { + return; + } + + if (!to || !(probe_user = strdup(to))) { + return; + } + + if ((probe_host = strchr(probe_user, '@'))) { + *probe_host++ = '\0'; + } + probe_euser = probe_user; + if ((p = strchr(probe_euser, '+'))) { + probe_euser = (p + 1); + } + + if (probe_euser && probe_host && (profile = sofia_glue_find_profile(probe_host))) { + sql = switch_mprintf("select status,rpid,presence_id from sip_dialogs " + "where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') order by rcd desc", + probe_euser, probe_host, probe_euser, probe_host); + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_dialog_callback, &dh); + + h.profile = profile; + + switch_safe_free(sql); + + sql = switch_mprintf("select sip_registrations.sip_user, " + "sip_registrations.sip_host, " + "sip_registrations.status, " + "sip_registrations.rpid, " + "'', " + "sip_dialogs.uuid, " + "sip_dialogs.state, " + "sip_dialogs.direction, " + "sip_dialogs.sip_to_user, " + "sip_dialogs.sip_to_host, " + + "sip_presence.status," + "sip_presence.rpid," + "sip_dialogs.presence_id, " + "sip_presence.open_closed," + "'%q','%q' " + "from sip_registrations " + + "left join sip_dialogs on " + "sip_dialogs.presence_id = sip_registrations.sip_user %q '@' %q sip_registrations.sip_host " + "or (sip_dialogs.sip_from_user = sip_registrations.sip_user " + "and sip_dialogs.sip_from_host = sip_registrations.sip_host) " + + "left join sip_presence on " + "(sip_registrations.sip_user=sip_presence.sip_user and sip_registrations.orig_server_host=sip_presence.sip_host and " + "sip_registrations.profile_name=sip_presence.profile_name) " + "where sip_dialogs.presence_id='%q@%q' or (sip_registrations.sip_user='%q' and " + "(sip_registrations.orig_server_host='%q' or sip_registrations.sip_host='%q' " + "or sip_registrations.presence_hosts like '%%%q%%'))", + dh.status, dh.rpid, + switch_sql_concat(), switch_sql_concat(), + probe_euser, probe_host, probe_euser, probe_host, probe_host, probe_host); + switch_assert(sql); + + if (mod_sofia_globals.debug_presence > 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s START_PRESENCE_PROBE_SQL\n", profile->name); + } + + if (mod_sofia_globals.debug_presence > 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s DUMP PRESENCE_PROBE_SQL:\n%s\n", profile->name, sql); + } + + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_resub_callback, &h); + + + if (!h.rowcount) { + h.noreg++; + switch_safe_free(sql); + /* find ones with presence_id defined that are not registred */ + sql = switch_mprintf("select sip_from_user, sip_from_host, 'Registered', '', '', " + "uuid, state, direction, " + "sip_to_user, sip_to_host," + "'%q','%q',presence_id, '','','' " + + "from sip_dialogs " + + "where (presence_id='%q@%q' or " + "(sip_from_user='%q' and (sip_from_host='%q' or sip_to_host='%q')))", + + dh.status, dh.rpid, probe_euser, probe_host, probe_euser, probe_host, probe_host); + + if (mod_sofia_globals.debug_presence > 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s START_PRESENCE_PROBE_SQL\n", profile->name); + } + + if (mod_sofia_globals.debug_presence > 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s DUMP PRESENCE_PROBE_SQL:\n%s\n", profile->name, sql); + } + + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_resub_callback, &h); + + if (mod_sofia_globals.debug_presence > 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s END_PRESENCE_PROBE_SQL\n\n", profile->name); + } + } + + if (!h.rowcount) { + switch_event_t *sevent; + if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "login", profile->name); + switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", probe_euser, probe_host); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "status", "Unregistered"); + switch_event_fire(&sevent); + } + } + + + sofia_glue_release_profile(profile); + switch_safe_free(sql); + } + + + switch_safe_free(probe_user); +} + +static void do_dialog_probe(sofia_profile_t *profile, switch_event_t *event) +{ + // Received SUBSCRIBE for "dialog" events. + // Return a complete list of dialogs for the monitored entity. + char *sql; + char *to = switch_event_get_header(event, "to"); + char *probe_user = NULL, *probe_euser, *probe_host, *p; + + if (!to || !(probe_user = strdup(to))) { + return; + } + + if ((probe_host = strchr(probe_user, '@'))) { + *probe_host++ = '\0'; + } + probe_euser = probe_user; + if ((p = strchr(probe_euser, '+'))) { + probe_euser = (p + 1); + } + + if (probe_euser && probe_host && (profile = sofia_glue_find_profile(probe_host))) { + char *sub_call_id = switch_event_get_header(event, "sub-call-id"); + struct rfc4235_helper *h4235 = {0}; + switch_memory_pool_t *pool; + + // We need all dialogs with presence_id matching the subscription entity, + // or from a registered set matching the subscription entity. + // We need the "proto" of the subscription in case it is for the special "conf" or "park". + sql = switch_mprintf( + "select sip_subscriptions.proto, '%q','%q'," + "sip_dialogs.uuid, sip_dialogs.call_id, sip_dialogs.state, sip_dialogs.direction, " + "sip_dialogs.sip_to_user, sip_dialogs.sip_to_host, " + "sip_dialogs.sip_from_user, sip_dialogs.sip_from_host, " + "sip_dialogs.contact, sip_dialogs.contact_user, sip_dialogs.contact_host, " + "sip_dialogs.sip_to_tag, sip_dialogs.sip_from_tag, sip_subscriptions.orig_proto " + "from sip_dialogs " + "left join sip_subscriptions on sip_subscriptions.call_id='%q' " + "left join sip_registrations on " + "(sip_dialogs.sip_from_user = sip_registrations.sip_user " + "and (sip_dialogs.sip_from_host = sip_registrations.orig_server_host or " + "sip_dialogs.sip_from_host = sip_registrations.sip_host) ) " + "where sip_dialogs.presence_id='%q@%q' or (sip_registrations.sip_user='%q' and " + "(sip_registrations.orig_server_host='%q' or sip_registrations.sip_host='%q' " + "or sip_registrations.presence_hosts like '%%%q%%'))", + probe_euser, probe_host, + sub_call_id, + probe_euser, probe_host, + probe_euser, probe_host, probe_host, probe_host); + switch_assert(sql); + + if (mod_sofia_globals.debug_presence > 0) { + switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_INFO, "%s START DIALOG_PROBE_SQL %s@%s\n", profile->name,probe_euser, probe_host); + } + + if (mod_sofia_globals.debug_presence > 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s DUMP DIALOG_PROBE_SQL:\n%s\n", profile->name, sql); + } + + switch_core_new_memory_pool(&pool); + h4235 = switch_core_alloc(pool, sizeof(*h4235)); + h4235->pool = pool; + h4235->profile = profile; + switch_core_hash_init(&h4235->hash, h4235->pool); + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_dialog_probe_callback, h4235); + switch_safe_free(sql); + if (mod_sofia_globals.debug_presence > 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s END DIALOG_PROBE_SQL\n\n", profile->name); + } + + // The dialog_probe_callback has built up the dialogs to be included in the NOTIFY. + // Now send the "full" dialog event to the triggering subscription. + sql = switch_mprintf("select call_id,expires,sub_to_user,sub_to_host,event,version, " + "'full',full_to,full_from,contact,expires,event,network_ip,network_port " + "from sip_subscriptions " + "where expires > -1 and hostname='%q' " + "and sub_to_user='%q' and sub_to_host='%q' " "and (event='dialog') and " + "call_id='%q'", + mod_sofia_globals.hostname, probe_euser, probe_host, sub_call_id); + if (mod_sofia_globals.debug_presence > 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s DUMP DIALOG_PROBE subscription sql:\n%s\n", profile->name, sql); + } + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_dialog_probe_notify_callback, h4235); + switch_safe_free(sql); + + sql = switch_mprintf("update sip_subscriptions set version=version+1 " + "where expires > -1 and hostname='%q' " + "and sub_to_user='%q' and sub_to_host='%q' " "and (event='dialog') and " + "call_id='%q'", + mod_sofia_globals.hostname, probe_euser, probe_host, sub_call_id); + + if (mod_sofia_globals.debug_presence > 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s DUMP DIALOG_PROBE set version sql:\n%s\n", profile->name, sql); + } + sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); + switch_safe_free(sql); + + sofia_glue_release_profile(profile); + switch_core_hash_destroy(&h4235->hash); + h4235 = NULL; + switch_core_destroy_memory_pool(&pool); + } + + switch_safe_free(probe_user); +} + + + static void actual_sofia_presence_event_handler(switch_event_t *event) { sofia_profile_t *profile = NULL; @@ -593,14 +846,19 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) char *sql = NULL; char *euser = NULL, *user = NULL, *host = NULL; char *call_info = switch_event_get_header(event, "presence-call-info"); + char *presence_source = switch_event_get_header(event, "presence-source"); char *call_info_state = switch_event_get_header(event, "presence-call-info-state"); - struct resub_helper h = { 0 }; switch_console_callback_match_t *matches; if (!mod_sofia_globals.running) { return; } + if (zstr(proto) || !strcasecmp(proto, "any")) { + proto = SOFIA_CHAT_PROTO; + } + + if (rpid && !strcasecmp(rpid, "n/a")) { rpid = NULL; } @@ -629,7 +887,8 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) "sip_subscriptions.contact,sip_subscriptions.call_id,sip_subscriptions.full_from," "sip_subscriptions.full_via,sip_subscriptions.expires,sip_subscriptions.user_agent," "sip_subscriptions.accept,sip_subscriptions.profile_name,sip_subscriptions.network_ip" - ",1,'%q','%q',sip_presence.status,sip_presence.rpid,sip_presence.open_closed " + ",1,'%q','%q',sip_presence.status,sip_presence.rpid,sip_presence.open_closed,'','','','','sip'," + " sip_subscriptions.full_to,sip_subscriptions.network_ip,sip_subscriptions.network_port " "from sip_subscriptions left join sip_presence on " "(sip_subscriptions.sub_to_user=sip_presence.sip_user and sip_subscriptions.sub_to_host=sip_presence.sip_host and " "sip_subscriptions.profile_name=sip_presence.profile_name) " @@ -642,7 +901,8 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) "sip_subscriptions.contact,sip_subscriptions.call_id,sip_subscriptions.full_from," "sip_subscriptions.full_via,sip_subscriptions.expires,sip_subscriptions.user_agent," "sip_subscriptions.accept,sip_subscriptions.profile_name,sip_subscriptions.network_ip" - ",1,'%q','%q',sip_presence.status,sip_presence.rpid,sip_presence.open_closed " + ",1,'%q','%q',sip_presence.status,sip_presence.rpid,sip_presence.open_closed,'','','','','sip'," + "sip_subscriptions.full_to,sip_subscriptions.network_ip,sip_subscriptions.network_port " "from sip_subscriptions left join sip_presence on " "(sip_subscriptions.sub_to_user=sip_presence.sip_user and sip_subscriptions.sub_to_host=sip_presence.sip_host and " "sip_subscriptions.profile_name=sip_presence.profile_name) " @@ -668,6 +928,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) helper.profile = profile; helper.event = NULL; sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_sub_callback, &helper); + sofia_glue_release_profile(profile); } } @@ -712,139 +973,22 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) switch (event->event_id) { case SWITCH_EVENT_PRESENCE_PROBE: - if (proto) { - char *to = switch_event_get_header(event, "to"); - char *probe_user = NULL, *probe_euser, *probe_host, *p; - struct dialog_helper dh = { { 0 } }; + { + char *probe_type = switch_event_get_header(event, "probe-type"); - if (strcasecmp(proto, SOFIA_CHAT_PROTO) != 0) { - goto done; + if (!probe_type || strcasecmp(probe_type, "dialog")) { + /* NORMAL PROBE */ + do_normal_probe(profile, event); + } else { + /* DIALOG PROBE */ + do_dialog_probe(profile, event); } - - - if (!to || !(probe_user = strdup(to))) { - goto done; - } - - if ((probe_host = strchr(probe_user, '@'))) { - *probe_host++ = '\0'; - } - probe_euser = probe_user; - if ((p = strchr(probe_euser, '+'))) { - probe_euser = (p + 1); - } - - if (probe_euser && probe_host && (profile = sofia_glue_find_profile(probe_host))) { - sql = switch_mprintf("select status,rpid,presence_id from sip_dialogs " - "where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q')", - probe_euser, probe_host, probe_euser, probe_host); - sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_dialog_callback, &dh); - - h.profile = profile; - - switch_safe_free(sql); - - sql = switch_mprintf("select sip_registrations.sip_user, " - "sip_registrations.sip_host, " - "sip_registrations.status, " - "sip_registrations.rpid, " - "'', " - "sip_dialogs.uuid, " - "sip_dialogs.state, " - "sip_dialogs.direction, " - "sip_dialogs.sip_to_user, " - "sip_dialogs.sip_to_host, " - - "sip_presence.status," - "sip_presence.rpid," - "sip_dialogs.presence_id, " - "sip_presence.open_closed," - "'%q','%q' " - "from sip_registrations " - - "left join sip_dialogs on " - "sip_dialogs.presence_id = sip_registrations.sip_user %q '@' %q sip_registrations.sip_host " - "or (sip_dialogs.sip_from_user = sip_registrations.sip_user " - "and sip_dialogs.sip_from_host = sip_registrations.sip_host) " - - "left join sip_presence on " - "(sip_registrations.sip_user=sip_presence.sip_user and sip_registrations.orig_server_host=sip_presence.sip_host and " - "sip_registrations.profile_name=sip_presence.profile_name) " - "where sip_dialogs.presence_id='%q@%q' or (sip_registrations.sip_user='%q' and " - "(sip_registrations.orig_server_host='%q' or sip_registrations.sip_host='%q' " - "or sip_registrations.presence_hosts like '%%%q%%'))", - dh.status, dh.rpid, - switch_sql_concat(), switch_sql_concat(), - probe_euser, probe_host, probe_euser, probe_host, probe_host, probe_host); - switch_assert(sql); - - if (mod_sofia_globals.debug_presence > 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s START_PRESENCE_PROBE_SQL\n", profile->name); - } - - if (mod_sofia_globals.debug_presence > 1) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s DUMP PRESENCE_PROBE_SQL:\n%s\n", profile->name, sql); - } - - sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_resub_callback, &h); - - - if (!h.rowcount) { - h.noreg++; - switch_safe_free(sql); - /* find ones with presence_id defined that are not registred */ - sql = switch_mprintf("select sip_from_user, sip_from_host, 'Registered', '', '', " - "uuid, state, direction, " - "sip_to_user, sip_to_host," - "'%q','%q',presence_id, '','','' " - - "from sip_dialogs " - - "where (presence_id='%q@%q' or " - "(sip_from_user='%q' and (sip_from_host='%q' or sip_to_host='%q')))", - - dh.status, dh.rpid, probe_euser, probe_host, probe_euser, probe_host, probe_host); - - if (mod_sofia_globals.debug_presence > 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s START_PRESENCE_PROBE_SQL\n", profile->name); - } - - if (mod_sofia_globals.debug_presence > 1) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s DUMP PRESENCE_PROBE_SQL:\n%s\n", profile->name, sql); - } - - sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_resub_callback, &h); - - if (mod_sofia_globals.debug_presence > 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s END_PRESENCE_PROBE_SQL\n\n", profile->name); - } - } - - if (!h.rowcount) { - switch_event_t *sevent; - if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "login", profile->name); - switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", probe_euser, probe_host); - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "status", "Unregistered"); - switch_event_fire(&sevent); - } - } - - - sofia_glue_release_profile(profile); - switch_safe_free(sql); - } - - - switch_safe_free(probe_user); } goto done; + default: break; - } - - + } if (!mod_sofia_globals.profile_hash) { goto done; @@ -907,10 +1051,17 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); } - sql = switch_mprintf("select status,rpid,presence_id from sip_dialogs where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q')", + sql = switch_mprintf("select status,rpid,presence_id from sip_dialogs " + "where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') order by rcd desc", euser, host, euser, host); sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_dialog_callback, &dh); switch_safe_free(sql); + + + if (dh.hits && presence_source && (!strcasecmp(presence_source, "register") || switch_stristr("register", status))) { + goto done; + } + if ((sql = switch_mprintf("select distinct sip_subscriptions.proto,sip_subscriptions.sip_user,sip_subscriptions.sip_host," "sip_subscriptions.sub_to_user,sip_subscriptions.sub_to_host,sip_subscriptions.event," @@ -918,19 +1069,21 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) "sip_subscriptions.full_via,sip_subscriptions.expires,sip_subscriptions.user_agent," "sip_subscriptions.accept,sip_subscriptions.profile_name" ",'%q','%q','%q',sip_presence.status,sip_presence.rpid,sip_presence.open_closed,'%q','%q'," - "sip_subscriptions.version, '%q' " + "sip_subscriptions.version, '%q',sip_subscriptions.orig_proto,sip_subscriptions.full_to," + "sip_subscriptions.network_ip, sip_subscriptions.network_port " "from sip_subscriptions " "left join sip_presence on " "(sip_subscriptions.sub_to_user=sip_presence.sip_user and sip_subscriptions.sub_to_host=sip_presence.sip_host and " "sip_subscriptions.profile_name=sip_presence.profile_name) " "where sip_subscriptions.version > -1 and sip_subscriptions.expires > -1 and " + "sip_subscriptions.proto='%q' and " "(event='%q' or event='%q') and sub_to_user='%q' " "and (sub_to_host='%q' or presence_hosts like '%%%q%%') " "and (sip_subscriptions.profile_name = '%q' or sip_subscriptions.presence_hosts != sip_subscriptions.sub_to_host) ", switch_str_nil(status), switch_str_nil(rpid), host, - dh.status,dh.rpid,dh.presence_id, + dh.status,dh.rpid,dh.presence_id, proto, event_type, alt_event_type, euser, host, host, profile->name))) { struct presence_helper helper = { 0 }; @@ -973,6 +1126,25 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) event->event_id == SWITCH_EVENT_PRESENCE_IN ? "IN" : "OUT", profile->name); } +#if 1 + if (event) { + const char *refresh = switch_event_get_header(event, "refresh"); + if (switch_true(refresh)) { + switch_event_t *s_event; + + if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", euser, host); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "to", "%s@%s", euser, host); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence"); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); + switch_event_fire(&s_event); + } + } + } +#endif + if (!zstr((char *) helper.stream.data)) { char *this_sql = (char *) helper.stream.data; char *next = NULL; @@ -1229,6 +1401,7 @@ static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Force-Direction", "inbound"); } + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "resub", "true"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", status); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); @@ -1270,6 +1443,391 @@ static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char return 0; } +char *get_display_name_from_contact(const char *in, char* dst) +{ + // name-addr = [ display-name ] LAQUOT addr-spec RAQUOT + // display-name = *(token LWS)/ quoted-string + // return whatever comes before the left angle bracket, stripped of whitespace and quotes + char *p; + char *buf; + + strcpy(dst, ""); + if (strchr(in, '<') && strchr(in, '>')) { + buf = strdup(in); + p = strchr(buf, '<'); + *p = '\0'; + if (!zstr(buf)) { + p = switch_strip_whitespace(buf); + if (p) { + if (*p == '"') { + if (end_of(p+1) == '"') { + char *q = strdup(p + 1); + end_of(q) = '\0'; + strcpy(dst, q); + switch_safe_free(q); + } + } else { + strcpy(dst, p); + } + switch_safe_free(p); + } + } + switch_safe_free(buf); + } + return dst; +} + +static int sofia_dialog_probe_callback(void *pArg, int argc, char **argv, char **columnNames) +{ + struct rfc4235_helper *h = (struct rfc4235_helper *) pArg; + + char *proto = argv[0]; + char *user = argv[1]; + char *host = argv[2]; + char *uuid = argv[3]; + char *call_id = argv[4]; + char *state = argv[5]; + char *direction = argv[6]; + char *to_user = argv[7]; + char *to_host = argv[8]; + char *from_user = argv[9]; + // char *from_host = argv[10]; + char *contact = switch_str_nil(argv[11]); + char *contact_user = switch_str_nil(argv[12]); + char *contact_host = switch_str_nil(argv[13]); + char *to_tag = switch_str_nil(argv[14]); + char *from_tag = switch_str_nil(argv[15]); + char *orig_proto = switch_str_nil(argv[16]); + + const char *event_status = ""; + char *data = NULL, *tmp; + char key[256] = ""; + char *local_user; + char *local_host; + char *remote_user; + char *remote_host; + char *remote_uri; + char *local_user_param = ""; + char remote_display_buf[512]; + char *buf_to_free = NULL; + int bInternal = 0; + int i; + int skip_proto = 0; + + if (mod_sofia_globals.debug_presence > 1) { + for (i = 0; i < argc; i++) { + switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_DEBUG, "sofia_dialog_probe_callback: %d [%s]=[%s]\n", i, columnNames[i], argv[i]); + } + } + + if (zstr(to_user) || zstr(contact_user)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "sofia_dialog_probe_callback: not enough info to generate a dialog entry\n"); + return 0; + } + + // Usually we report the dialogs FROM the probed user. The exception is when the monitored endpoint is internal, + // and its presence_id is set in the dialplan. Reverse the direction if this is not a registered entity. + if (!strcmp(direction, "inbound") && strcmp(user, from_user) ) { + // If inbound and the entity is not the caller (i.e. internal to FS), then the direction is reversed + // because it is not going through the B2BUA + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "sofia_dialog_probe_callback: endpt is internal\n"); + direction = !strcasecmp(direction, "outbound") ? "inbound" : "outbound"; + bInternal = 1; + } + + if (!strcasecmp(direction, "outbound")) { + direction = "recipient"; + } + else { + direction = "initiator"; + } + + if (!zstr(orig_proto) && !strcmp(orig_proto, SOFIA_CHAT_PROTO)) { + skip_proto = 1; + } + + local_host = to_host; + if (proto && !strcasecmp(proto, "queue")) { + local_user = "queue"; + local_user_param = switch_mprintf(";fifo=%s", to_user); + event_status = "hold"; + if (skip_proto) { + buf_to_free = switch_mprintf("sip:%s", to_user); + } else { + buf_to_free = switch_mprintf("sip:queue+%s", to_user); + } + remote_uri = buf_to_free; + strcpy(remote_display_buf, "queue"); + remote_user = to_user; + remote_host = local_host; + } + else if (proto && !strcasecmp(proto, "park")) { + local_user = "park"; + local_user_param = switch_mprintf(";fifo=%s", to_user); + event_status = "hold"; + if (skip_proto) { + buf_to_free = switch_mprintf("sip:%s", to_user); + } else { + buf_to_free = switch_mprintf("sip:park+%s", to_user); + } + remote_uri = buf_to_free; + strcpy(remote_display_buf, "park"); + remote_user = to_user; + remote_host = local_host; + } + else if (proto && !strcasecmp(proto, "conf")) { + local_user = "conference"; + local_user_param = switch_mprintf(";conference=%s", to_user); + if (skip_proto) { + buf_to_free = switch_mprintf("sip:%s@%s", to_user, host); + } else { + buf_to_free = switch_mprintf("sip:conf+%s@%s", to_user, host); + } + remote_uri = buf_to_free; + strcpy(remote_display_buf, "conference"); + remote_user = to_user; + remote_host = local_host; + } + else if (bInternal) { + local_user = to_user; + get_display_name_from_contact(contact, remote_display_buf); + buf_to_free = sofia_glue_strip_uri(contact); + remote_uri = buf_to_free; + remote_user = contact_user; + remote_host = contact_host; + } else { + local_user = from_user; + buf_to_free = switch_mprintf("**%s@%s", from_user, local_host); + remote_uri = buf_to_free; + strcpy(remote_display_buf, to_user); + remote_user = to_user; + remote_host = local_host; + } + + switch_snprintf(key, sizeof(key), "%s%s", user, host); + data = switch_core_hash_find(h->hash, key); + if (!data) { + data = ""; + } + tmp = switch_core_sprintf(h->pool, "%s" + "\n" + " %s\n" + " \n" + " sip:%s@%s%s\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " sip:%s@%s\n" + " \n" + " \n" + "\n", + data, + uuid, call_id, to_tag, from_tag, direction, + state, + local_user, local_user, local_host, local_user_param, + local_user, local_host, + !strcasecmp(event_status, "hold") ? "no" : "yes", + remote_display_buf, remote_user, remote_host, + remote_uri + ); + switch_core_hash_insert(h->hash, key, tmp); + switch_safe_free(buf_to_free); + + h->rowcount++; + + return 0; +} + +static void send_presence_notify(sofia_profile_t *profile, + const char *full_to, + const char *full_from, + const char *contact, + const char *expires, + const char *call_id, + const char *event, + const char *remote_ip, + const char *remote_port, + const char *ct, + const char *pl, + const char *call_info + ) +{ + char sstr[128] = ""; + nua_handle_t *nh; + int exptime = 0; + char expires_str[10] = ""; + char *tmp, *route = NULL; + sip_cseq_t *cseq = NULL; + uint32_t callsequence; + uint32_t now = (uint32_t) switch_epoch_time_now(NULL); + + if (expires) { + long ltmp = atol(expires); + + if (ltmp > 0) { + exptime = (ltmp - now); + } else { + exptime = 0; + } + } + + + switch_mutex_lock(profile->ireg_mutex); + if (!profile->cseq_base) { + profile->cseq_base = (now - 1312693200) * 10; + } + callsequence = ++profile->cseq_base; + switch_mutex_unlock(profile->ireg_mutex); + + + nh = nua_handle(profile->nua, NULL, TAG_END()); + cseq = sip_cseq_create(nh->nh_home, callsequence, SIP_METHOD_NOTIFY); + nua_handle_bind(nh, &mod_sofia_globals.destroy_private); + + if (exptime > 0) { + switch_snprintf(sstr, sizeof(sstr), "active;expires=%u", (unsigned) exptime); + } else { + switch_snprintf(sstr, sizeof(sstr), "terminated;reason=noresource"); + } + + + tmp = (char *)contact; + contact = sofia_glue_get_url_from_contact(tmp, 0); + + if (remote_ip && remote_port) { + route = switch_mprintf("sip:%s:%s", remote_ip, remote_port); + } + + if (mod_sofia_globals.debug_presence > 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SEND PRES NOTIFY:\n" + "route[%s]\ncontact[%s]\nto[%s]\nfrom[%s]\nurl[%s]\ncall_id[%s]\nexpires_str[%s]\n" + "event[%s]\nct[%s]\npl[%s]\ncall_info[%s]\nexptime[%ld]\n", + route, + contact, + full_to, + full_from, + profile->url, + call_id, + expires_str, + event, + switch_str_nil(ct), + switch_str_nil(pl), + switch_str_nil(call_info), + (long)exptime + ); + + + } + + nua_notify(nh, + NUTAG_NEWSUB(1), + TAG_IF(route, NUTAG_PROXY(route)), + NUTAG_URL(contact), + SIPTAG_FROM_STR(full_to), + SIPTAG_TO_STR(full_from), + SIPTAG_CONTACT_STR(profile->url), + SIPTAG_CALL_ID_STR(call_id), + TAG_IF(*expires_str, SIPTAG_EXPIRES_STR(expires_str)), + SIPTAG_SUBSCRIPTION_STATE_STR(sstr), + SIPTAG_EVENT_STR(event), + TAG_IF(!zstr(ct), SIPTAG_CONTENT_TYPE_STR(ct)), + TAG_IF(!zstr(pl), SIPTAG_PAYLOAD_STR(pl)), + TAG_IF(!zstr(call_info), SIPTAG_CALL_INFO_STR(call_info)), + TAG_IF(!exptime, SIPTAG_EXPIRES_STR("0")), + SIPTAG_CSEQ(cseq), + TAG_END()); + + switch_safe_free(route); + + +} + + +static int sofia_dialog_probe_notify_callback(void *pArg, int argc, char **argv, char **columnNames) +{ + struct rfc4235_helper *sh = (struct rfc4235_helper *) pArg; + char key[256] = ""; + char *data = NULL; + char *call_id = argv[0]; + char *expires = argv[1]; + char *user = argv[2]; + char *host = argv[3]; + char *event = argv[4]; + char *version = argv[5]; + char *notify_state = argv[6]; + char *full_to = argv[7]; + char *full_from = argv[8]; + char *contact = argv[9]; + char *remote_ip = argv[10]; + char *remote_port = argv[11]; + + switch_stream_handle_t stream = { 0 }; + char *to; + const char *pl = NULL; + const char *ct = "application/dialog-info+xml"; + + + if (mod_sofia_globals.debug_presence > 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, + "SEND DIALOG\nTo: \t%s@%s\nFrom: \t%s@%s\nCall-ID: \t%s\n", + user, host, user, host, call_id); + } + + to = switch_mprintf("sip:%s@%s", user, host); + + SWITCH_STANDARD_STREAM(stream); + + if (zstr(version)) { + version = "0"; + } + + stream.write_function(&stream, + "\n" + "\n", + version, + notify_state, to); + + switch_snprintf(key, sizeof(key), "%s%s", user, host); + + data = switch_core_hash_find(sh->hash, key); + + if (data) { + stream.write_function(&stream, "%s\n", data); + } + + stream.write_function(&stream, "\n"); + pl = stream.data; + ct = "application/dialog-info+xml"; + + if (mod_sofia_globals.debug_presence > 0 && pl) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "send payload:\n%s\n", pl); + } + + + send_presence_notify(sh->profile, + full_to, + full_from, + contact, + expires, + call_id, + event, + remote_ip, + remote_port, + ct, + pl, + NULL + ); + + + switch_safe_free(to); + switch_safe_free(stream.data); + + return 0; +} + static char *translate_rpid(char *in) { char *r = in; @@ -1408,12 +1966,17 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * struct presence_helper *helper = (struct presence_helper *) pArg; char *pl = NULL; char *clean_id = NULL, *id = NULL; + char *proto = argv[0]; char *user = argv[1]; char *host = argv[2]; char *sub_to_user = argv[3]; char *event = argv[5]; + char *contact = argv[6]; char *call_id = argv[7]; + char *full_from = argv[8]; + //char *full_via = argv[9]; + char *expires = argv[10]; char *user_agent = argv[11]; char *profile_name = argv[13]; @@ -1426,27 +1989,33 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * char *dialog_rpid = NULL; const char *ct = "no/idea"; - nua_handle_t *nh; + char *to = NULL; char *open; char *prpid; - time_t exptime = switch_epoch_time_now(NULL) + 3600; + int is_dialog = 0; sofia_profile_t *ext_profile = NULL, *profile = helper->profile; - char sstr[128] = ""; - int kill_handle = 0; - char expires_str[10] = ""; + char status_line[256] = ""; char *version = "0"; char *presence_id = NULL; char *free_me = NULL; + int holding = 0; + char *orig_proto = NULL; + int skip_proto = 0; + char *full_to = NULL; + char *ip = NULL; + char *port = 0; + + if (mod_sofia_globals.debug_presence > 0) { + int i; + for(i = 0; i < argc; i++) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "arg %d[%s] = [%s]\n", i, columnNames[i], argv[i]); + } + DUMP_EVENT(helper->event); + } - //int i; - - //for(i = 0; i < argc; i++) { - //printf("arg %d[%s] = [%s]\n", i, columnNames[i], argv[i]); - //} - if (argc > 18) { if (!zstr(argv[17])) { status = argv[17]; @@ -1462,6 +2031,10 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * dialog_rpid = argv[21]; version = argv[22]; presence_id = argv[23]; + orig_proto = argv[24]; + full_to = argv[25]; + ip = argv[26]; + port = argv[27]; } if (!zstr(presence_id) && strchr(presence_id, '@')) { @@ -1477,6 +2050,10 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * } + if (!zstr(orig_proto) && !strcmp(orig_proto, SOFIA_CHAT_PROTO)) { + skip_proto = 1; + } + in = helper->event && helper->event->event_id == SWITCH_EVENT_PRESENCE_IN; if (zstr(rpid)) { @@ -1495,50 +2072,45 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * } } + if (status && !strncasecmp(status, "hold", 4)) { + holding = 1; + } + if (profile_name && strcasecmp(profile_name, helper->profile->name)) { if ((ext_profile = sofia_glue_find_profile(profile_name))) { profile = ext_profile; } } - if (!(nh = nua_handle_by_call_id(profile->nua, call_id))) { - if (mod_sofia_globals.debug_presence > 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to find handle for call id %s\n", call_id); - } - - goto end; - } - - if (expires) { - long tmp = atol(expires); - if (tmp > 0) { - exptime = tmp - switch_epoch_time_now(NULL); // - SUB_OVERLAP; - } else { - exptime = tmp; - } - } - - if (!rpid) { - rpid = "unknown"; - } - - if (!strcasecmp(proto, SOFIA_CHAT_PROTO)) { + if (!strcasecmp(proto, SOFIA_CHAT_PROTO) || skip_proto) { clean_id = switch_mprintf("sip:%s@%s", sub_to_user, sub_to_host); } else { clean_id = switch_mprintf("sip:%s+%s@%s", proto, sub_to_user, sub_to_host); } + + + if (!rpid) { + rpid = "unknown"; + } + + // if (!strcasecmp(proto, SOFIA_CHAT_PROTO) || skip_proto) { + // clean_id = switch_mprintf("sip:%s@%s", sub_to_user, sub_to_host); + //} else { + // clean_id = switch_mprintf("sip:%s+%s@%s", proto, sub_to_user, sub_to_host); + //} + if (mod_sofia_globals.debug_presence > 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "SEND PRESENCE\nTo: \t%s@%s\nFrom: \t%s@%s\nCall-ID: \t%s\nProfile:\t%s [%s]\n\n", user, host, sub_to_user, sub_to_host, call_id, profile_name, helper->profile->name); } - if (!strcasecmp(sub_to_host, host)) { + if (!strcasecmp(sub_to_host, host) && !skip_proto) { /* same host */ id = switch_mprintf("sip:%s+%s@%s", proto, sub_to_user, sub_to_host); - } else if (strcasecmp(proto, SOFIA_CHAT_PROTO)) { + } else if (strcasecmp(proto, SOFIA_CHAT_PROTO) && !skip_proto) { /*encapsulate */ id = switch_mprintf("sip:%s+%s+%s@%s", proto, sub_to_user, sub_to_host, host); } else { @@ -1552,9 +2124,11 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * if (helper->event) { switch_stream_handle_t stream = { 0 }; const char *direction = switch_str_nil(switch_event_get_header(helper->event, "presence-call-direction")); - const char *force_direction = switch_str_nil(switch_event_get_header(helper->event, "force-direction")); + //const char *force_direction = switch_str_nil(switch_event_get_header(helper->event, "force-direction")); const char *uuid = switch_str_nil(switch_event_get_header(helper->event, "unique-id")); const char *event_status = switch_str_nil(switch_event_get_header(helper->event, "status")); + const char *resub = switch_str_nil(switch_event_get_header(helper->event, "resub")); + const char *force_event_status = switch_str_nil(switch_event_get_header(helper->event, "force-status")); const char *astate = switch_str_nil(switch_event_get_header(helper->event, "astate")); const char *answer_state = switch_str_nil(switch_event_get_header(helper->event, "answer-state")); const char *dft_state; @@ -1565,6 +2139,18 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * char *clean_from_user = NULL; int force_status = 0; + if (event_status && !strncasecmp(event_status, "hold", 4)) { + holding = 1; + } + + if (force_event_status && !event_status) { + event_status = force_event_status; + } + + if (event_status && !strncasecmp(event_status, "hold", 4)) { + holding = 1; + } + if (!strcasecmp(direction, "inbound")) { from_id = switch_str_nil(switch_event_get_header(helper->event, "Caller-Destination-Number")); } else { @@ -1582,8 +2168,17 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * SWITCH_STANDARD_STREAM(stream); } - if (!zstr(force_direction)) { - direction = force_direction; + if (is_dialog) { + // Usually we report the dialogs FROM the probed user. The exception is when the monitored endpoint is internal, + // and its presence_id is set in the dialplan. Reverse the direction if this is not a registered entity. + const char *caller = switch_str_nil(switch_event_get_header(helper->event, "caller-username")); + if (!strcmp(direction, "inbound") && strcmp(sub_to_user, caller)) { + // If inbound and the entity is not the caller (i.e. internal to FS), then the direction is reversed + // because it is not going through the B2BUA + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "sofia_presence_sub_callback: endpt is internal\n"); + direction = !strcasecmp(direction, "outbound") ? "inbound" : "outbound"; + } + } if (!strcasecmp(direction, "outbound")) { @@ -1621,10 +2216,6 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * } } - if (!strcasecmp(event_status, "hold")) { - astate = "early"; - } - if (!strcasecmp(astate, "answered")) { astate = "confirmed"; } @@ -1634,6 +2225,7 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * } if (is_dialog) { + if (!strcasecmp(astate, "ringing")) { if (!strcasecmp(direction, "recipient")) { astate = "early"; @@ -1642,6 +2234,10 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * } } + if (holding) { + astate = "early"; + } + stream.write_function(&stream, "\n", uuid, direction); stream.write_function(&stream, "%s\n", astate); } else { @@ -1649,6 +2245,7 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * astate = "early"; } } + if (!strcasecmp(astate, "early") || !strcasecmp(astate, "confirmed")) { @@ -1659,8 +2256,8 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * if (!zstr(clean_to_user) && !zstr(clean_from_user)) { stream.write_function(&stream, "\nsip:%s@%s\n", clean_to_user, clean_to_user, host); stream.write_function(&stream, "\n", clean_to_user, host); - stream.write_function(&stream, "\n", - !strcasecmp(event_status, "hold") ? "no" : "yes"); + stream.write_function(&stream, "\n", holding ? "no" : "yes"); + stream.write_function(&stream, "\n\n"); if (switch_true(switch_event_get_header(helper->event, "Presence-Privacy"))) { stream.write_function(&stream, "\nsip:anonymous@anonymous.invalid\n"); @@ -1670,13 +2267,30 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * } stream.write_function(&stream, "\n", clean_to_user, host); stream.write_function(&stream, "\n"); - } else if (!strcasecmp(proto, "park")) { - stream.write_function(&stream, "\nsip:parking@%s;fifo=%s\n", + } else if (!strcasecmp(proto, "queue")) { + stream.write_function(&stream, "\nsip:queue@%s;fifo=%s\n", host, !zstr(clean_to_user) ? clean_to_user : "unknown"); - stream.write_function(&stream, "\n", host); + stream.write_function(&stream, "\n", host); stream.write_function(&stream, "\n\n\n"); - stream.write_function(&stream, "\nsip:%s\n", uuid); - stream.write_function(&stream, "\n", uuid); + stream.write_function(&stream, "\nsip:%s\n", uuid); + if (skip_proto) { + stream.write_function(&stream, "\n", uuid); + } else { + stream.write_function(&stream, "\n", uuid); + } + + stream.write_function(&stream, "\n"); + } else if (!strcasecmp(proto, "park")) { + stream.write_function(&stream, "\nsip:park@%s;slot=%s\n", + host, !zstr(clean_to_user) ? clean_to_user : "unknown"); + stream.write_function(&stream, "\n", host); + stream.write_function(&stream, "\n\n\n"); + stream.write_function(&stream, "\nsip:%s\n", uuid); + if (skip_proto) { + stream.write_function(&stream, "\n", uuid); + } else { + stream.write_function(&stream, "\n", uuid); + } stream.write_function(&stream, "\n"); } else if (!strcasecmp(proto, "conf")) { stream.write_function(&stream, "\nsip:conference@%s;conference=%s\n", @@ -1684,7 +2298,11 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * stream.write_function(&stream, "\n", host); stream.write_function(&stream, "\n\n\n"); stream.write_function(&stream, "\nsip:%s@%s\n", uuid, host); - stream.write_function(&stream, "\n", uuid, host); + if (skip_proto) { + stream.write_function(&stream, "\n", uuid, host); + } else { + stream.write_function(&stream, "\n", uuid, host); + } stream.write_function(&stream, "\n"); } } @@ -1703,9 +2321,9 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * ct = "application/dialog-info+xml"; } - if (!zstr(astate) && !zstr(uuid) && helper && helper->stream.data && strcmp(helper->last_uuid, uuid)) { + if (!zstr(astate) && !zstr(uuid) && + helper && helper->stream.data && strcmp(helper->last_uuid, uuid) && strcasecmp(astate, "terminated") && strchr(uuid, '-')) { helper->stream.write_function(&helper->stream, "update sip_dialogs set state='%s' where uuid='%s';", astate, uuid); - switch_copy_string(helper->last_uuid, uuid, sizeof(helper->last_uuid)); } @@ -1714,45 +2332,62 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * switch_set_string(status_line, status); if (in) { - const char *direction = switch_event_get_header(helper->event, "Caller-Direction"); - const char *op, *what = "Ring"; - - if (direction && !strcasecmp(direction, "outbound")) { - op = switch_event_get_header(helper->event, "Other-Leg-Caller-ID-Number"); - } else { - op = switch_event_get_header(helper->event, "Caller-Callee-ID-Number"); - } - - if (zstr(op)) { - op = switch_event_get_header(helper->event, "Caller-Destination-Number"); - } - - if (direction) { - what = strcasecmp(direction, "outbound") ? "Call" : "Ring"; - } - - if (!strcmp(astate, "early")) { - if (zstr(op)) { - switch_snprintf(status_line, sizeof(status_line), "%sing", what); - } else { - switch_snprintf(status_line, sizeof(status_line), "%s %s", what, op); - } - - rpid = "on-the-phone"; - force_status = 1; - - } else if (!strcmp(astate, "confirmed")) { - if (zstr(op)) { - switch_snprintf(status_line, sizeof(status_line), "On The Phone"); - } else { - switch_snprintf(status_line, sizeof(status_line), "Talk %s", op); - } - - rpid = "on-the-phone"; - force_status = 1; - } - open = "open"; + + if (switch_false(resub)) { + + const char *direction = switch_event_get_header(helper->event, "Caller-Direction"); + const char *op, *what = "Ring"; + + if (direction && !strcasecmp(direction, "outbound")) { + op = switch_event_get_header(helper->event, "Other-Leg-Caller-ID-Number"); + } else { + op = switch_event_get_header(helper->event, "Caller-Callee-ID-Number"); + } + + if (zstr(op)) { + op = switch_event_get_header(helper->event, "Caller-Destination-Number"); + } + + if (direction) { + what = strcasecmp(direction, "outbound") ? "Call" : "Ring"; + } + + if (!strcmp(astate, "early")) { + if (!zstr(op)) { + //switch_snprintf(status_line, sizeof(status_line), "%sing", what); + //} else { + switch_snprintf(status_line, sizeof(status_line), "%s %s", what, op); + } + + rpid = "on-the-phone"; + force_status = 1; + + } else if (!strcmp(astate, "confirmed")) { + if (!zstr(op)) { + if (sofia_test_pflag(profile, PFLAG_PRESENCE_PRIVACY)) { + switch_snprintf(status_line, sizeof(status_line), "On The Phone"); + } else { + switch_snprintf(status_line, sizeof(status_line), "Talk %s", op); + } + } else { + switch_snprintf(status_line, sizeof(status_line), "On The Phone"); + } + + rpid = "on-the-phone"; + force_status = 1; + } + + + + if (!strcmp(status, "hold")) { + rpid = "on-the-phone"; + if (!zstr(op)) { + switch_snprintf(status_line, sizeof(status_line), "Hold %s", op); + force_status = 1; + } + } + } } else { open = "closed"; } @@ -1767,12 +2402,18 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * status = dialog_status; switch_set_string(status_line, status); } + + + + if (!zstr(force_event_status)) { + switch_set_string(status_line, force_event_status); + } + if (!zstr(dialog_rpid)) { prpid = rpid = dialog_rpid; } - - + pl = gen_pidf(user_agent, clean_id, profile->url, open, rpid, prpid, status_line, &ct); } @@ -1803,44 +2444,17 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * } - if (helper->event){ + if (!is_dialog && helper->event && !switch_stristr("registered", status_line)){ const char *uuid = switch_event_get_header_nil(helper->event, "unique-id"); - - if (!zstr(uuid) && strchr(uuid, '-')) { + const char *register_source = switch_event_get_header_nil(helper->event, "register-source"); + + if (!zstr(uuid) && strchr(uuid, '-') && !zstr(status_line) && !zstr(rpid) && (zstr(register_source) || strcasecmp(register_source, "register"))) { char *sql = switch_mprintf("update sip_dialogs set rpid='%q',status='%q' where uuid='%q'", rpid, status_line, uuid); sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE); } } - - nua_handle_bind(nh, &mod_sofia_globals.keep_private); - - if (helper->event && helper->event->event_id == SWITCH_EVENT_PRESENCE_OUT) { - switch_set_string(sstr, "terminated;reason=noresource"); - switch_set_string(expires_str, "0"); - kill_handle = 1; - } else if (exptime > 0) { - switch_snprintf(sstr, sizeof(sstr), "active;expires=%u", (unsigned) exptime); - } else { - unsigned delta = (unsigned) (exptime * -1); - switch_snprintf(sstr, sizeof(sstr), "active;expires=%u", delta); - switch_snprintf(expires_str, sizeof(expires_str), "%u", delta); - if (nh && nh->nh_ds && nh->nh_ds->ds_usage) { - nua_dialog_usage_set_refresh_range(nh->nh_ds->ds_usage, delta, delta); - } - } - - if (mod_sofia_globals.debug_presence > 0 && pl) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "send payload:\n%s\n", pl); - } - - nua_notify(nh, - TAG_IF(*expires_str, SIPTAG_EXPIRES_STR(expires_str)), - SIPTAG_SUBSCRIPTION_STATE_STR(sstr), SIPTAG_EVENT_STR(event), SIPTAG_CONTENT_TYPE_STR(ct), SIPTAG_PAYLOAD_STR(pl), TAG_END()); - - nua_handle_unref(nh); - - end: + send_presence_notify(profile, full_to, full_from, contact, expires, call_id, event, ip, port, ct, pl, NULL); switch_safe_free(free_me); @@ -1853,25 +2467,24 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * switch_safe_free(pl); switch_safe_free(to); - if (nh && kill_handle) { - nua_handle_destroy(nh); - } - return 0; } static int sofia_presence_mwi_callback(void *pArg, int argc, char **argv, char **columnNames) { - char *sub_to_user = argv[3]; - char *sub_to_host = argv[15]; + //char *sub_to_user = argv[3]; + //char *sub_to_host = argv[4]; char *event = argv[5]; + char *contact = argv[6]; char *call_id = argv[7]; + char *full_from = argv[8]; char *expires = argv[10]; char *profile_name = argv[13]; char *body = argv[15]; - char *id = NULL; - nua_handle_t *nh; - int expire_sec = atoi(expires); + char *full_to = argv[16]; + char *remote_ip = argv[17]; + char *remote_port = argv[18]; + struct mwi_helper *h = (struct mwi_helper *) pArg; sofia_profile_t *ext_profile = NULL, *profile = h->profile; @@ -1881,31 +2494,23 @@ static int sofia_presence_mwi_callback(void *pArg, int argc, char **argv, char * } } - if (!(nh = nua_handle_by_call_id(h->profile->nua, call_id))) { - if (profile->debug) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Cannot find handle for %s\n", call_id); - } - goto end; - } + send_presence_notify(profile, + full_to, + full_from, + contact, + expires, + call_id, + event, + remote_ip, + remote_port, + "application/simple-message-summary", + body, + NULL + ); - id = switch_mprintf("sip:%s@%s", sub_to_user, sub_to_host); - expire_sec = (int) (expire_sec - switch_epoch_time_now(NULL)); - if (expire_sec < 0) { - expire_sec = 3600; - } - - nua_handle_bind(nh, &mod_sofia_globals.keep_private); - nua_notify(nh, SIPTAG_SUBSCRIPTION_STATE_STR("active"), - SIPTAG_EVENT_STR(event), SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"), SIPTAG_PAYLOAD_STR(body), TAG_END()); - - nua_handle_unref(nh); - - switch_safe_free(id); h->total++; - end: - if (ext_profile) { sofia_glue_release_profile(ext_profile); } @@ -1948,14 +2553,11 @@ static int broadsoft_sla_notify_callback(void *pArg, int argc, char **argv, char char key[256] = ""; char *data = NULL, *tmp; char *call_id = argv[0]; - char *expires = argv[1]; + //char *expires = argv[1]; char *user = argv[2]; char *host = argv[3]; char *event = argv[4]; int i; - char sstr[128] = "", expires_str[128] = ""; - time_t exptime = 3600; - nua_handle_t *nh; if (mod_sofia_globals.debug_sla > 1) { for (i = 0; i < argc; i++) { @@ -1965,19 +2567,7 @@ static int broadsoft_sla_notify_callback(void *pArg, int argc, char **argv, char switch_snprintf(key, sizeof(key), "%s%s", user, host); data = switch_core_hash_find(sh->hash, key); - - if (expires) { - long tmp = atol(expires); - exptime = tmp - switch_epoch_time_now(NULL); - } - - if (exptime > 0) { - switch_snprintf(sstr, sizeof(sstr), "active;expires=%u", (unsigned) exptime); - } else { - switch_snprintf(sstr, sizeof(sstr), "terminated;reason=noresource"); - } - - switch_snprintf(expires_str, sizeof(expires_str), "%u", (unsigned) exptime); + data = switch_core_hash_find(sh->hash, key); @@ -1987,26 +2577,23 @@ static int broadsoft_sla_notify_callback(void *pArg, int argc, char **argv, char tmp = switch_core_sprintf(sh->pool, ";appearance-index=*;appearance-state=idle", host); } - if (!strcasecmp(event, "line-seize") && (nh = nua_handle_by_call_id(sh->profile->nua, call_id))) { + + if (!strcasecmp(event, "line-seize")) { char *hack; if ((hack = (char *) switch_stristr("=seized", tmp))) { switch_snprintf(hack, 7, "=idle "); } - nua_notify(nh, - SIPTAG_EXPIRES_STR("0"), - SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"), SIPTAG_EVENT_STR("line-seize"), SIPTAG_CALL_INFO_STR(tmp), TAG_END()); - nua_handle_unref(nh); - return 0; } - if (!strcasecmp(event, "call-info") && (nh = nua_handle_by_call_id(sh->profile->nua, call_id))) { - nua_notify(nh, - TAG_IF(*expires_str, SIPTAG_EXPIRES_STR(expires_str)), - SIPTAG_SUBSCRIPTION_STATE_STR(sstr), SIPTAG_EVENT_STR("call-info"), SIPTAG_CALL_INFO_STR(tmp), TAG_END()); - nua_handle_unref(nh); + if (mod_sofia_globals.debug_sla > 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DB PRES NOTIFY: [%s]\n[%s]\n[%s]\n[%s]\n[%s]\n[%s]\n[%s]\n[%s]\n[%s]\n", + argv[5], argv[6], argv[7], argv[8], call_id, event, argv[9], argv[10], tmp); + } - + + send_presence_notify(sh->profile, argv[5], argv[6], argv[7], argv[8], call_id, event, argv[9], argv[10], NULL, NULL, tmp); + return 0; } @@ -2127,13 +2714,13 @@ static void sync_sla(sofia_profile_t *profile, const char *to_user, const char * if (unseize) { - sql = switch_mprintf("select call_id,expires,sub_to_user,sub_to_host,event " + sql = switch_mprintf("select call_id,expires,sub_to_user,sub_to_host,event,full_to,full_from,contact,expires,network_ip,network_port " "from sip_subscriptions " "where version > -1 and expires > -1 and hostname='%q' " "and sub_to_user='%q' and sub_to_host='%q' " "and (event='call-info' or event='line-seize')", mod_sofia_globals.hostname, to_user, to_host); } else { - sql = switch_mprintf("select call_id,expires,sub_to_user,sub_to_host,event " + sql = switch_mprintf("select call_id,expires,sub_to_user,sub_to_host,event,full_to,full_from,contact,expires,network_ip,network_port " "from sip_subscriptions " "where version > -1 and expires > -1 and hostname='%q' " "and sub_to_user='%q' and sub_to_host='%q' " "and (event='call-info')", mod_sofia_globals.hostname, to_user, to_host); @@ -2171,7 +2758,7 @@ void sofia_presence_handle_sip_i_subscribe(int status, tagi_t tags[]) { - long exp_delta; + long exp_delta = 0; char exp_delta_str[30] = ""; sip_to_t const *to; const char *from_user = NULL, *from_host = NULL; @@ -2179,11 +2766,14 @@ void sofia_presence_handle_sip_i_subscribe(int status, char *my_to_user = NULL; char *sql, *event = NULL; char *proto = "sip"; + char *orig_proto = ""; + char *alt_proto = NULL; char *d_user = NULL; char *contact_str = ""; const char *call_id = NULL; char *to_str = NULL; char *full_from = NULL; + char *full_to = NULL; char *full_via = NULL; char *full_agent = NULL; char *sstr; @@ -2194,6 +2784,8 @@ void sofia_presence_handle_sip_i_subscribe(int status, const char *ipv6; const char *contact_user; sofia_nat_parse_t np = { { 0 } }; + int found_proto = 0; + char to_tag[13] = ""; if (!sip) { return; @@ -2207,6 +2799,8 @@ void sofia_presence_handle_sip_i_subscribe(int status, return; } + switch_stun_random_string(to_tag, 12, NULL); + //contact_host = sip->sip_contact->m_url->url_host; contact_user = sip->sip_contact->m_url->url_user; @@ -2214,19 +2808,6 @@ void sofia_presence_handle_sip_i_subscribe(int status, event = sip_header_as_string(nh->nh_home, (void *) sip->sip_event); - - /* the following could be refactored back to the calling event handler in sofia.c XXX MTK */ - if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) { - if (sip->sip_request->rq_url->url_user && !strncmp(sip->sip_request->rq_url->url_user, "sla-agent", sizeof("sla-agent"))) { - /* only fire this on <200 to try to avoid resubscribes. probably better ways to do this? */ - if (status < 200) { - sofia_sla_handle_sip_i_subscribe(nua, contact_str, profile, nh, sip, de, tags); - } - switch_safe_free(contact_str); - return; - } - } - if (to) { to_str = switch_mprintf("sip:%s@%s", to->a_url->url_user, to->a_url->url_host); } @@ -2249,7 +2830,7 @@ void sofia_presence_handle_sip_i_subscribe(int status, } if ((exp_delta = sip->sip_expires ? sip->sip_expires->ex_delta : 3600)) { - if (profile->force_subscription_expires) { + if ((profile->force_subscription_expires > 0) && (profile->force_subscription_expires < (uint32_t)exp_delta)) { exp_delta = profile->force_subscription_expires; } } @@ -2277,16 +2858,24 @@ void sofia_presence_handle_sip_i_subscribe(int status, nua_respond(nh, SIP_404_NOT_FOUND, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END()); goto end; } + + found_proto++; } call_id = sip->sip_call_id->i_id; full_from = sip_header_as_string(nh->nh_home, (void *) sip->sip_from); + full_to = sip_header_as_string(nh->nh_home, (void *) sip->sip_to); full_via = sip_header_as_string(nh->nh_home, (void *) sip->sip_via); + if (sip->sip_expires && sip->sip_expires->ex_delta > 31536000) { sip->sip_expires->ex_delta = 31536000; } + if (sofia_test_pflag(profile, PFLAG_PRESENCE_MAP) && !found_proto && (alt_proto = switch_ivr_check_presence_mapping(to_user, to_host))) { + orig_proto = proto; + proto = alt_proto; + } if ((sub_state == nua_substate_active) && (switch_stristr("dialog", (const char *) event))) { @@ -2295,7 +2884,7 @@ void sofia_presence_handle_sip_i_subscribe(int status, sql = switch_mprintf("update sip_subscriptions " "set expires=%ld " "where call_id='%q' and event='dialog' and hostname='%q' ", - (long) switch_epoch_time_now(NULL) + (exp_delta * 2), + (long) switch_epoch_time_now(NULL) + exp_delta, call_id, mod_sofia_globals.hostname); @@ -2330,6 +2919,7 @@ void sofia_presence_handle_sip_i_subscribe(int status, } else { sip_accept_t *ap = sip->sip_accept; char accept[256] = ""; + full_agent = sip_header_as_string(nh->nh_home, (void *) sip->sip_user_agent); while (ap) { switch_snprintf(accept + strlen(accept), sizeof(accept) - strlen(accept), "%s%s ", ap->ac_type, ap->ac_next ? "," : ""); @@ -2338,13 +2928,13 @@ void sofia_presence_handle_sip_i_subscribe(int status, sql = switch_mprintf("insert into sip_subscriptions " "(proto,sip_user,sip_host,sub_to_user,sub_to_host,presence_hosts,event,contact,call_id,full_from," - "full_via,expires,user_agent,accept,profile_name,hostname,network_port,network_ip) " - "values ('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld,'%q','%q','%q','%q','%d','%q')", + "full_via,expires,user_agent,accept,profile_name,hostname,network_port,network_ip, orig_proto, full_to) " + "values ('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld,'%q','%q','%q','%q','%d','%q','%q','%q;tag=%q')", proto, from_user, from_host, to_user, to_host, profile->presence_hosts ? profile->presence_hosts : to_host, event, contact_str, call_id, full_from, full_via, - //sofia_test_pflag(profile, PFLAG_MULTIREG) ? switch_epoch_time_now(NULL) + exp_delta : exp_delta * -1, - (long) switch_epoch_time_now(NULL) + (exp_delta * 2), - full_agent, accept, profile->name, mod_sofia_globals.hostname, np.network_port, np.network_ip); + (long) switch_epoch_time_now(NULL) + exp_delta, + full_agent, accept, profile->name, mod_sofia_globals.hostname, + np.network_port, np.network_ip, orig_proto, full_to, to_tag); switch_assert(sql != NULL); @@ -2356,15 +2946,16 @@ void sofia_presence_handle_sip_i_subscribe(int status, sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); sstr = switch_mprintf("active;expires=%ld", exp_delta); - } - - switch_mutex_unlock(profile->ireg_mutex); + } + + switch_mutex_unlock(profile->ireg_mutex); } if (status < 200) { char *sticky = NULL; char *contactstr = profile->url, *cs = NULL; char *p = NULL, *new_contactstr = NULL; + if (np.is_nat) { char params[128] = ""; @@ -2403,7 +2994,7 @@ void sofia_presence_handle_sip_i_subscribe(int status, if (nh && nh->nh_ds && nh->nh_ds->ds_usage) { /* nua_dialog_usage_set_refresh_range(nh->nh_ds->ds_usage, exp_delta + SUB_OVERLAP, exp_delta + SUB_OVERLAP); */ - nua_dialog_usage_set_refresh_range(nh->nh_ds->ds_usage, exp_delta * 2, exp_delta * 2); + nua_dialog_usage_set_refresh_range(nh->nh_ds->ds_usage, exp_delta, exp_delta); } if (contactstr && (p = strchr(contactstr, '@'))) { @@ -2413,8 +3004,11 @@ void sofia_presence_handle_sip_i_subscribe(int status, new_contactstr = switch_mprintf("", to_user, p); } } - + + sip_to_tag(nh->nh_home, sip->sip_to, to_tag); + nua_respond(nh, SIP_202_ACCEPTED, + SIPTAG_TO(sip->sip_to), TAG_IF(new_contactstr, SIPTAG_CONTACT_STR(new_contactstr)), NUTAG_WITH_THIS_MSG(de->data->e_msg), SIPTAG_SUBSCRIPTION_STATE_STR(sstr), SIPTAG_EXPIRES_STR(exp_delta_str), TAG_IF(sticky, NUTAG_PROXY(sticky)), TAG_END()); @@ -2464,6 +3058,7 @@ void sofia_presence_handle_sip_i_subscribe(int status, if (!strcasecmp(event, "line-seize")) { char *full_call_info = NULL; char *p; + switch_time_t now; if (sip->sip_call_info) { full_call_info = sip_header_as_string(nh->nh_home, (void *) sip->sip_call_info); @@ -2488,9 +3083,10 @@ void sofia_presence_handle_sip_i_subscribe(int status, } sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); - sql = switch_mprintf("insert into sip_dialogs (sip_from_user,sip_from_host,call_info,call_info_state,hostname,expires) " - "values ('%q','%q','%q','seized','%q',%ld)", - to_user, to_host, switch_str_nil(p), mod_sofia_globals.hostname, switch_epoch_time_now(NULL) + exp_delta); + now = switch_epoch_time_now(NULL); + sql = switch_mprintf("insert into sip_dialogs (sip_from_user,sip_from_host,call_info,call_info_state,hostname,expires,rcd) " + "values ('%q','%q','%q','seized','%q',%ld,%ld)", + to_user, to_host, switch_str_nil(p), mod_sofia_globals.hostname, switch_epoch_time_now(NULL) + exp_delta, (long)now); if (mod_sofia_globals.debug_sla > 1) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SEIZE SQL %s\n", sql); @@ -2534,6 +3130,9 @@ void sofia_presence_handle_sip_i_subscribe(int status, if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", protocol); + if (!zstr(orig_proto)) { + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "orig_proto", orig_proto); + } switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "login", profile->name); switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, to_host); switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "rpid", "active"); @@ -2544,7 +3143,10 @@ void sofia_presence_handle_sip_i_subscribe(int status, } else if (to_user && (strcasecmp(proto, SOFIA_CHAT_PROTO) != 0)) { if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", proto); - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "long", profile->name); + if (!zstr(orig_proto)) { + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "orig_proto", orig_proto); + } + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "login", profile->name); switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host); switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "to", "%s%s%s@%s", proto, "+", to_user, to_host); switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto-specific-event-name", event); @@ -2557,6 +3159,10 @@ void sofia_presence_handle_sip_i_subscribe(int status, } } else { if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) { + if (!strcasecmp(event, "dialog")) { + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "probe-type", "dialog"); + } + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "login", profile->name); switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host); @@ -2566,6 +3172,7 @@ void sofia_presence_handle_sip_i_subscribe(int status, switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "event_type", "presence"); switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "sub-call-id", call_id); switch_event_fire(&sevent); } } @@ -2579,6 +3186,10 @@ void sofia_presence_handle_sip_i_subscribe(int status, if (full_from) { su_free(nh->nh_home, full_from); } + if (full_to) { + su_free(nh->nh_home, full_to); + } + if (full_via) { su_free(nh->nh_home, full_via); } @@ -2589,11 +3200,14 @@ void sofia_presence_handle_sip_i_subscribe(int status, switch_safe_free(d_user); switch_safe_free(to_str); switch_safe_free(contact_str); + switch_safe_free(alt_proto); if (!sent_reply) { nua_respond(nh, 481, "INVALID SUBSCRIPTION", TAG_END()); } - + + nua_handle_destroy(nh); + } @@ -2612,7 +3226,7 @@ sofia_gateway_subscription_t *sofia_find_gateway_subscription(sofia_gateway_t *g void sofia_presence_handle_sip_r_subscribe(int status, char const *phrase, nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip, - sofia_dispatch_event_t *de, + sofia_dispatch_event_t *de, tagi_t tags[]) { sip_event_t const *o = NULL; @@ -2629,14 +3243,6 @@ void sofia_presence_handle_sip_r_subscribe(int status, return; } - /* the following could possibly be refactored back towards the calling event handler in sofia.c XXX MTK */ - if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) { - if (!strcasecmp(o->o_type, "dialog") && msg_params_find(o->o_params, "sla")) { - sofia_sla_handle_sip_r_subscribe(status, phrase, nua, profile, nh, sofia_private, sip, de, tags); - return; - } - } - if (!sofia_private || !sofia_private->gateway) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Gateway information missing\n"); return; @@ -2652,6 +3258,7 @@ void sofia_presence_handle_sip_r_subscribe(int status, /* Update the subscription status for the subscription */ switch (status) { case 200: + case 202: /* TODO: in the spec it is possible for the other side to change the original expiry time, * this needs to be researched (eg, what sip header this information will be in) and implemented. * Although, since it seems the sofia stack is pretty much handling the subscription expiration @@ -2667,10 +3274,11 @@ void sofia_presence_handle_sip_r_subscribe(int status, gw_sub_ptr->state = SUB_STATE_FAILED; if (sofia_private) { - nua_handle_destroy(sofia_private->gateway->sub_nh); - sofia_private->gateway->sub_nh = NULL; - nua_handle_bind(sofia_private->gateway->sub_nh, NULL); - sofia_private_free(sofia_private); + if (sofia_private->gateway->sub_nh) { + nua_handle_bind(sofia_private->gateway->sub_nh, NULL); + nua_handle_destroy(sofia_private->gateway->sub_nh); + sofia_private->gateway->sub_nh = NULL; + } } else { nua_handle_destroy(nh); } @@ -2679,32 +3287,13 @@ void sofia_presence_handle_sip_r_subscribe(int status, } } -struct cpc { - sofia_profile_t *profile; - sofia_dispatch_event_t *de; -}; -static int sofia_counterpath_crutch(void *pArg, int argc, char **argv, char **columnNames) +static int sofia_presence_send_sql(void *pArg, int argc, char **argv, char **columnNames) { - nua_handle_t *nh; - struct cpc *crutch = (struct cpc *) pArg; - char *call_id = argv[0]; - char *pl = argv[1]; - char *event_type = argv[2]; - long exp_delta = atol(argv[3]); - - if ((nh = nua_handle_by_call_id(crutch->profile->nua, call_id))) { - char sstr[128] = "", expstr[128] = ""; - switch_snprintf(expstr, sizeof(expstr), "%d", exp_delta); - switch_snprintf(sstr, sizeof(sstr), "active;expires=%u", exp_delta); - nua_notify(nh, - NUTAG_WITH_THIS_MSG(crutch->de->data->e_msg), - SIPTAG_EXPIRES_STR(expstr), - SIPTAG_SUBSCRIPTION_STATE_STR(sstr), SIPTAG_EVENT_STR(event_type), - SIPTAG_CONTENT_TYPE_STR("application/pidf+xml"), SIPTAG_PAYLOAD_STR(pl), TAG_END()); - nua_handle_unref(nh); - } + sofia_profile_t *profile = (sofia_profile_t *) pArg; + send_presence_notify(profile, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], NULL); + return 0; } @@ -2747,15 +3336,6 @@ void sofia_presence_handle_sip_i_publish(nua_t *nua, sofia_profile_t *profile, n from = sip->sip_from; payload = sip->sip_payload; - /* the following could instead be refactored back to the calling event handler in sofia.c XXX MTK */ - if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) { - /* also it probably is unsafe to dereference so many things in a row without testing XXX MTK */ - if (sip->sip_request->rq_url->url_user && !strncmp(sip->sip_request->rq_url->url_user, "sla-agent", sizeof("sla-agent"))) { - sofia_sla_handle_sip_i_publish(nua, profile, nh, sip, de, tags); - return; - } - } - contact_str = sofia_glue_gen_contact_str(profile, sip, de, NULL); if (from) { @@ -2764,7 +3344,7 @@ void sofia_presence_handle_sip_i_publish(nua_t *nua, sofia_profile_t *profile, n } exp_delta = (sip->sip_expires ? sip->sip_expires->ex_delta : 3600); - if (profile->force_publish_expires) { + if ((profile->force_publish_expires > 0) && (profile->force_publish_expires < (uint32_t)exp_delta)) { exp_delta = profile->force_publish_expires; } @@ -2842,14 +3422,12 @@ void sofia_presence_handle_sip_i_publish(nua_t *nua, sofia_profile_t *profile, n } } else if (contact_str) { - struct cpc crutch; - - crutch.profile = profile; - crutch.de = de; - sql = switch_mprintf("select call_id,'%q','%q','%ld' from sip_subscriptions where sub_to_user='%q' and sub_to_host='%q' " - "and contact = '%q' ", payload->pl_data ? payload->pl_data : "", event_type, exp_delta, - from_user, from_host, contact_str); - sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_counterpath_crutch, &crutch); + sql = switch_mprintf("select full_to, full_from, contact, expires, call_id, event, network_ip, network_port, " + "'application/pidf+xml' as ct,'%q' as pt " + " from sip_subscriptions where sub_to_user='%q' and sub_to_host='%q' and event='%q'" + "and contact = '%q' ", switch_str_nil(payload->pl_data), from_user, from_host, event_type); + + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_send_sql, profile); switch_safe_free(sql); } @@ -2990,6 +3568,9 @@ void sofia_presence_handle_sip_i_message(int status, if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); + + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_proto", proto); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", from_addr); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_user", from_user); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_host", from_host); @@ -3068,6 +3649,30 @@ void sofia_presence_set_chat_hash(private_object_t *tech_pvt, sip_t const *sip) switch_mutex_unlock(tech_pvt->profile->flag_mutex); } + +void sofia_presence_check_subscriptions(sofia_profile_t *profile, time_t now) +{ + char *sql; + + if (now) { + sql = switch_mprintf("select full_to, full_from, contact, expires, call_id, event, network_ip, network_port, " + "NULL as ct, NULL as pt " + " from sip_subscriptions where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%q'", + (long) now, mod_sofia_globals.hostname); + + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_send_sql, profile); + switch_safe_free(sql); + + sql = switch_mprintf("delete from sip_subscriptions where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%q'", + (long) now, mod_sofia_globals.hostname); + sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); + } + + + +} + + /* For Emacs: * Local Variables: * mode:c diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 253caf890c..ea7ca0a6cf 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -65,10 +65,73 @@ static void sofia_reg_new_handle(sofia_gateway_t *gateway_ptr, int attach) } } +static void sofia_reg_new_sub_handle(sofia_gateway_t *gateway_ptr, int attach) +{ + char *user_via = NULL; + char *register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy); + int ss_state = nua_callstate_authenticating; + + /* check for NAT and place a Via header if necessary (hostname or non-local IP) */ + if (register_host && sofia_glue_check_nat(gateway_ptr->profile, register_host)) { + user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport); + } + + if (gateway_ptr->sub_nh) { + nua_handle_bind(gateway_ptr->sub_nh, NULL); + nua_handle_destroy(gateway_ptr->sub_nh); + gateway_ptr->sub_nh = NULL; + sofia_private_free(gateway_ptr->sofia_private); + } + + gateway_ptr->sub_nh = nua_handle(gateway_ptr->profile->nua, NULL, + NUTAG_URL(gateway_ptr->register_proxy), + TAG_IF(user_via, SIPTAG_VIA_STR(user_via)), + SIPTAG_TO_STR(gateway_ptr->register_to), + NUTAG_CALLSTATE_REF(ss_state), SIPTAG_FROM_STR(gateway_ptr->register_from), TAG_END()); + if (attach) { + if (!gateway_ptr->sofia_private) { + gateway_ptr->sofia_private = malloc(sizeof(*gateway_ptr->sofia_private)); + switch_assert(gateway_ptr->sofia_private); + } + memset(gateway_ptr->sofia_private, 0, sizeof(*gateway_ptr->sofia_private)); + + gateway_ptr->sofia_private->gateway = gateway_ptr; + nua_handle_bind(gateway_ptr->sub_nh, gateway_ptr->sofia_private); + } + + switch_safe_free(register_host); + switch_safe_free(user_via); +} + +static void sofia_reg_kill_sub(sofia_gateway_t *gateway_ptr) +{ + + if (gateway_ptr->sub_nh) { + nua_handle_bind(gateway_ptr->sub_nh, NULL); + } + + if (gateway_ptr->sub_state != SUB_STATE_SUBED && gateway_ptr->sub_state != SUB_STATE_UNSUBSCRIBE) { + if (gateway_ptr->sub_nh) { + nua_handle_destroy(gateway_ptr->sub_nh); + gateway_ptr->sub_nh = NULL; + } + return; + } + + if (gateway_ptr->sub_nh) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "UN-Subbing %s\n", gateway_ptr->name); + nua_unsubscribe(gateway_ptr->sub_nh, NUTAG_URL(gateway_ptr->register_url), TAG_END()); + } +} + static void sofia_reg_kill_reg(sofia_gateway_t *gateway_ptr) { - if (gateway_ptr->state != REG_STATE_REGED) { + if (gateway_ptr->nh) { + nua_handle_bind(gateway_ptr->nh, NULL); + } + + if (gateway_ptr->state != REG_STATE_REGED && gateway_ptr->state != REG_STATE_UNREGISTER) { if (gateway_ptr->nh) { nua_handle_destroy(gateway_ptr->nh); gateway_ptr->nh = NULL; @@ -76,19 +139,10 @@ static void sofia_reg_kill_reg(sofia_gateway_t *gateway_ptr) return; } - /* - if (!gateway_ptr->nh) { - sofia_reg_new_handle(gateway_ptr, SWITCH_FALSE); - } - */ - if (gateway_ptr->nh) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "UN-Registering %s\n", gateway_ptr->name); nua_unregister(gateway_ptr->nh, NUTAG_URL(gateway_ptr->register_url), NUTAG_REGISTRAR(gateway_ptr->register_proxy), TAG_END()); } - - - } void sofia_reg_fire_custom_gateway_state_event(sofia_gateway_t *gateway, int status, const char *phrase) @@ -111,9 +165,15 @@ void sofia_reg_fire_custom_gateway_state_event(sofia_gateway_t *gateway, int sta void sofia_reg_unregister(sofia_profile_t *profile) { sofia_gateway_t *gateway_ptr; + sofia_gateway_subscription_t *gw_sub_ptr; + switch_mutex_lock(mod_sofia_globals.hash_mutex); for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) { + if (gateway_ptr->nh) { + nua_handle_bind(gateway_ptr->nh, NULL); + } + if (gateway_ptr->sofia_private) { sofia_private_free(gateway_ptr->sofia_private); } @@ -122,6 +182,12 @@ void sofia_reg_unregister(sofia_profile_t *profile) sofia_reg_kill_reg(gateway_ptr); } + for (gw_sub_ptr = gateway_ptr->subscriptions; gw_sub_ptr; gw_sub_ptr = gw_sub_ptr->next) { + if (gw_sub_ptr->state == SUB_STATE_SUBED) { + sofia_reg_kill_sub(gateway_ptr); + } + } + } switch_mutex_unlock(mod_sofia_globals.hash_mutex); } @@ -140,24 +206,14 @@ void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now) sofia_gateway_subscription_t *gw_sub_ptr; for (gw_sub_ptr = gateway_ptr->subscriptions; gw_sub_ptr; gw_sub_ptr = gw_sub_ptr->next) { - int ss_state = nua_callstate_authenticating; sub_state_t ostate = gw_sub_ptr->state; - char *user_via = NULL; - char *register_host = NULL; if (!now) { gw_sub_ptr->state = ostate = SUB_STATE_UNSUBED; gw_sub_ptr->expires_str = "0"; } - register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy); - - /* check for NAT and place a Via header if necessary (hostname or non-local IP) */ - if (register_host && sofia_glue_check_nat(gateway_ptr->profile, register_host)) { - user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport); - } - - switch_safe_free(register_host); + gateway_ptr->sub_state = gw_sub_ptr->state; switch (ostate) { case SUB_STATE_NOSUB: @@ -168,37 +224,17 @@ void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now) break; case SUB_STATE_UNSUBSCRIBE: gw_sub_ptr->state = SUB_STATE_NOSUB; - - /* not tested .. */ - nua_unsubscribe(gateway_ptr->nh, - NUTAG_URL(gateway_ptr->register_url), - TAG_IF(user_via, SIPTAG_VIA_STR(user_via)), - SIPTAG_EVENT_STR(gw_sub_ptr->event), - SIPTAG_ACCEPT_STR(gw_sub_ptr->content_type), - SIPTAG_TO_STR(gateway_ptr->register_from), - SIPTAG_FROM_STR(gateway_ptr->register_from), SIPTAG_CONTACT_STR(gateway_ptr->register_contact), TAG_NULL()); - + sofia_reg_kill_sub(gateway_ptr); break; case SUB_STATE_UNSUBED: - gateway_ptr->sub_nh = nua_handle(gateway_ptr->profile->nua, NULL, - NUTAG_URL(gateway_ptr->register_proxy), - TAG_IF(user_via, SIPTAG_VIA_STR(user_via)), - SIPTAG_TO_STR(gateway_ptr->register_to), - NUTAG_CALLSTATE_REF(ss_state), SIPTAG_FROM_STR(gateway_ptr->register_from), TAG_END()); + + sofia_reg_new_sub_handle(gateway_ptr, 1); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "subscribing to [%s] on gateway [%s]\n", gw_sub_ptr->event, gateway_ptr->name); - gateway_ptr->sofia_private = malloc(sizeof(*gateway_ptr->sofia_private)); - switch_assert(gateway_ptr->sofia_private); - - memset(gateway_ptr->sofia_private, 0, sizeof(*gateway_ptr->sofia_private)); - - gateway_ptr->sofia_private->gateway = gateway_ptr; - nua_handle_bind(gateway_ptr->nh, gateway_ptr->sofia_private); - if (now) { nua_subscribe(gateway_ptr->sub_nh, NUTAG_URL(gateway_ptr->register_url), - TAG_IF(user_via, SIPTAG_VIA_STR(user_via)), SIPTAG_EVENT_STR(gw_sub_ptr->event), SIPTAG_ACCEPT_STR(gw_sub_ptr->content_type), SIPTAG_TO_STR(gateway_ptr->register_from), @@ -210,7 +246,6 @@ void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now) } else { nua_unsubscribe(gateway_ptr->sub_nh, NUTAG_URL(gateway_ptr->register_url), - TAG_IF(user_via, SIPTAG_VIA_STR(user_via)), SIPTAG_EVENT_STR(gw_sub_ptr->event), SIPTAG_ACCEPT_STR(gw_sub_ptr->content_type), SIPTAG_FROM_STR(gateway_ptr->register_from), @@ -233,7 +268,7 @@ void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now) } break; } - switch_safe_free(user_via); + } } switch_mutex_unlock(profile->gw_mutex); @@ -676,10 +711,10 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_del_callback, profile); if (now) { - switch_snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and expires <= %ld and hostname='%s'", + switch_snprintfv(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and expires <= %ld and hostname='%q'", (long) now, mod_sofia_globals.hostname); } else { - switch_snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and hostname='%s'", mod_sofia_globals.hostname); + switch_snprintfv(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and hostname='%q'", mod_sofia_globals.hostname); } sofia_glue_actually_execute_sql(profile, sql, NULL); @@ -687,11 +722,11 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) if (now) { - switch_snprintf(sql, sizeof(sql), "select call_id from sip_shared_appearance_dialogs where hostname='%s' " + switch_snprintfv(sql, sizeof(sql), "select call_id from sip_shared_appearance_dialogs where hostname='%q' " "and profile_name='%s' and expires <= %ld", mod_sofia_globals.hostname, profile->name, (long) now); sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_sla_dialog_del_callback, profile); - switch_snprintf(sql, sizeof(sql), "delete from sip_shared_appearance_dialogs where expires > 0 and hostname='%s' and expires <= %ld", + switch_snprintfv(sql, sizeof(sql), "delete from sip_shared_appearance_dialogs where expires > 0 and hostname='%q' and expires <= %ld", mod_sofia_globals.hostname, (long) now); @@ -700,19 +735,19 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) if (now) { - switch_snprintf(sql, sizeof(sql), "delete from sip_presence where expires > 0 and expires <= %ld and hostname='%s'", + switch_snprintfv(sql, sizeof(sql), "delete from sip_presence where expires > 0 and expires <= %ld and hostname='%q'", (long) now, mod_sofia_globals.hostname); } else { - switch_snprintf(sql, sizeof(sql), "delete from sip_presence where expires > 0 and hostname='%s'", mod_sofia_globals.hostname); + switch_snprintfv(sql, sizeof(sql), "delete from sip_presence where expires > 0 and hostname='%q'", mod_sofia_globals.hostname); } sofia_glue_actually_execute_sql(profile, sql, NULL); if (now) { - switch_snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and expires <= %ld and hostname='%s'", + switch_snprintfv(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and expires <= %ld and hostname='%q'", (long) now, mod_sofia_globals.hostname); } else { - switch_snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and hostname='%s'", mod_sofia_globals.hostname); + switch_snprintfv(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and hostname='%q'", mod_sofia_globals.hostname); } sofia_glue_actually_execute_sql(profile, sql, NULL); @@ -722,27 +757,20 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) "select call_id from sip_subscriptions where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%s'", (long) now, mod_sofia_globals.hostname); } else { - switch_snprintf(sql, sizeof(sql), "select sub_to_user,sub_to_host,call_id from sip_subscriptions where expires >= -1 and hostname='%s'", + switch_snprintfv(sql, sizeof(sql), "select sub_to_user,sub_to_host,call_id from sip_subscriptions where expires >= -1 and hostname='%q'", mod_sofia_globals.hostname); } sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_sub_del_callback, profile); - if (now) { - switch_snprintf(sql, sizeof(sql), "delete from sip_subscriptions where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%s'", - (long) now, mod_sofia_globals.hostname); - } else { - switch_snprintf(sql, sizeof(sql), "delete from sip_subscriptions where expires >= -1 and hostname='%s'", mod_sofia_globals.hostname); - } - - sofia_glue_actually_execute_sql(profile, sql, NULL); + sofia_presence_check_subscriptions(profile, now); if (now) { - switch_snprintf(sql, sizeof(sql), "delete from sip_dialogs where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%s'", + switch_snprintfv(sql, sizeof(sql), "delete from sip_dialogs where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%q'", (long) now, mod_sofia_globals.hostname); } else { - switch_snprintf(sql, sizeof(sql), "delete from sip_dialogs where expires >= -1 and hostname='%s'", mod_sofia_globals.hostname); + switch_snprintfv(sql, sizeof(sql), "delete from sip_dialogs where expires >= -1 and hostname='%q'", mod_sofia_globals.hostname); } sofia_glue_actually_execute_sql(profile, sql, NULL); @@ -833,24 +861,24 @@ void sofia_reg_check_sync(sofia_profile_t *profile) sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_del_callback, profile); - switch_snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and hostname='%s'", mod_sofia_globals.hostname); + switch_snprintfv(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and hostname='%q'", mod_sofia_globals.hostname); sofia_glue_actually_execute_sql(profile, sql, NULL); - switch_snprintf(sql, sizeof(sql), "delete from sip_presence where expires > 0 and hostname='%s'", mod_sofia_globals.hostname); + switch_snprintfv(sql, sizeof(sql), "delete from sip_presence where expires > 0 and hostname='%q'", mod_sofia_globals.hostname); sofia_glue_actually_execute_sql(profile, sql, NULL); - switch_snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and hostname='%s'", mod_sofia_globals.hostname); + switch_snprintfv(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and hostname='%q'", mod_sofia_globals.hostname); sofia_glue_actually_execute_sql(profile, sql, NULL); - switch_snprintf(sql, sizeof(sql), "select sub_to_user,sub_to_host,call_id from sip_subscriptions where expires >= -1 and hostname='%s'", + switch_snprintfv(sql, sizeof(sql), "select sub_to_user,sub_to_host,call_id from sip_subscriptions where expires >= -1 and hostname='%q'", mod_sofia_globals.hostname); sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_sub_del_callback, profile); - switch_snprintf(sql, sizeof(sql), "delete from sip_subscriptions where expires >= -1 and hostname='%s'", mod_sofia_globals.hostname); + switch_snprintfv(sql, sizeof(sql), "delete from sip_subscriptions where expires >= -1 and hostname='%q'", mod_sofia_globals.hostname); sofia_glue_actually_execute_sql(profile, sql, NULL); - switch_snprintf(sql, sizeof(sql), "delete from sip_dialogs where expires >= -1 and hostname='%s'", mod_sofia_globals.hostname); + switch_snprintfv(sql, sizeof(sql), "delete from sip_dialogs where expires >= -1 and hostname='%q'", mod_sofia_globals.hostname); sofia_glue_actually_execute_sql(profile, sql, NULL); switch_mutex_unlock(profile->ireg_mutex); @@ -871,10 +899,10 @@ char *sofia_reg_find_reg_url(sofia_profile_t *profile, const char *user, const c cbt.len = len; if (host) { - switch_snprintf(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%s' and (sip_host='%s' or presence_hosts like '%%%s%%')", + switch_snprintfv(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')", user, host, host); } else { - switch_snprintf(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%s'", user); + switch_snprintfv(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%q'", user); } @@ -900,10 +928,10 @@ switch_console_callback_match_t *sofia_reg_find_reg_url_multi(sofia_profile_t *p } if (host) { - switch_snprintf(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%s' and (sip_host='%s' or presence_hosts like '%%%s%%')", + switch_snprintfv(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')", user, host, host); } else { - switch_snprintf(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%s'", user); + switch_snprintfv(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%q'", user); } @@ -924,10 +952,10 @@ switch_console_callback_match_t *sofia_reg_find_reg_url_with_positive_expires_mu } if (host) { - switch_snprintf(sql, sizeof(sql), "select contact,expires from sip_registrations where sip_user='%s' and (sip_host='%s' or presence_hosts like '%%%s%%')", + switch_snprintfv(sql, sizeof(sql), "select contact,expires from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')", user, host, host); } else { - switch_snprintf(sql, sizeof(sql), "select contact,expires from sip_registrations where sip_user='%s'", user); + switch_snprintfv(sql, sizeof(sql), "select contact,expires from sip_registrations where sip_user='%q'", user); } sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_reg_find_reg_with_positive_expires_callback, &cbt); @@ -1011,7 +1039,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand char contact_str[1024] = ""; uint8_t multi_reg = 0, multi_reg_contact = 0, avoid_multi_reg = 0; uint8_t stale = 0, forbidden = 0; - auth_res_t auth_res; + auth_res_t auth_res = AUTH_OK; long exptime = 300; switch_event_t *event; const char *rpid = "unknown"; @@ -1343,7 +1371,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand } } - if (auth_res != AUTH_OK && !stale) { + if (auth_res != AUTH_OK && auth_res != AUTH_RENEWED && !stale) { if (auth_res == AUTH_FORBIDDEN) { nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END()); forbidden = 1; @@ -1401,7 +1429,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand } /* Log line added to support Fail2Ban */ if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "SIP auth challenge (%s) on sofia profile '%s' " + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SIP auth challenge (%s) on sofia profile '%s' " "for [%s@%s] from ip %s\n", (regtype == REG_INVITE) ? "INVITE" : "REGISTER", profile->name, to_user, to_host, network_ip); } @@ -1455,38 +1483,51 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand const char *realm = reg_host; char *url = NULL; char *contact = NULL; + switch_bool_t update_registration = SWITCH_FALSE; if (auth_params) { username = switch_event_get_header(auth_params, "sip_auth_username"); realm = switch_event_get_header(auth_params, "sip_auth_realm"); } + if (auth_res != AUTH_RENEWED) { + if (multi_reg) { - if (multi_reg) { + if (delete_subs) { + if (reg_count == 1) { + sql = switch_mprintf("update sip_subscriptions set expires=%ld where sip_user='%q' and sip_host='%q' and contact='%q'", + (long) switch_epoch_time_now(NULL), to_user, sub_host, contact_str); + sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); + } + } - if (delete_subs) { - if (reg_count == 1) { - sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'", - to_user, sub_host, contact_str); + + if (multi_reg_contact) { + sql = + switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, reg_host, contact_str); + } else { + sql = switch_mprintf("delete from sip_registrations where call_id='%q'", call_id); + } + } else { + if (delete_subs) { + sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host); sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); } + sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", to_user, reg_host); } - - - if (multi_reg_contact) { - sql = - switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, reg_host, contact_str); - } else { - sql = switch_mprintf("delete from sip_registrations where call_id='%q'", call_id); - } + switch_mutex_lock(profile->ireg_mutex); + sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); } else { - if (delete_subs) { - sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host); - sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); + char buf[32] = ""; + sql = switch_mprintf("select count(*) from sip_registrations where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, reg_host, contact_str); + + switch_mutex_lock(profile->ireg_mutex); + + sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, buf, sizeof(buf)); + switch_safe_free(sql); + if (atoi(buf) > 0) { + update_registration = SWITCH_TRUE; } - sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", to_user, reg_host); } - switch_mutex_lock(profile->ireg_mutex); - sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); switch_find_local_ip(guess_ip4, sizeof(guess_ip4), NULL, AF_INET); @@ -1499,21 +1540,25 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand switch_safe_free(url); switch_safe_free(contact); - sql = switch_mprintf("insert into sip_registrations " - "(call_id,sip_user,sip_host,presence_hosts,contact,status,rpid,expires," - "user_agent,server_user,server_host,profile_name,hostname,network_ip,network_port,sip_username,sip_realm," - "mwi_user,mwi_host, orig_server_host, orig_hostname) " - "values ('%q','%q', '%q','%q','%q','%q', '%q', %ld, '%q', '%q', '%q', '%q', '%q', '%q', '%q','%q','%q','%q','%q','%q','%q')", - call_id, to_user, reg_host, profile->presence_hosts ? profile->presence_hosts : reg_host, - contact_str, reg_desc, rpid, (long) switch_epoch_time_now(NULL) + (long) exptime + 60, - agent, from_user, guess_ip4, profile->name, mod_sofia_globals.hostname, network_ip, network_port_c, username, realm, - mwi_user, mwi_host, guess_ip4, mod_sofia_globals.hostname); - + if (!update_registration) { + sql = switch_mprintf("insert into sip_registrations " + "(call_id,sip_user,sip_host,presence_hosts,contact,status,rpid,expires," + "user_agent,server_user,server_host,profile_name,hostname,network_ip,network_port,sip_username,sip_realm," + "mwi_user,mwi_host, orig_server_host, orig_hostname) " + "values ('%q','%q', '%q','%q','%q','%q', '%q', %ld, '%q', '%q', '%q', '%q', '%q', '%q', '%q','%q','%q','%q','%q','%q','%q')", + call_id, to_user, reg_host, profile->presence_hosts ? profile->presence_hosts : reg_host, + contact_str, reg_desc, rpid, (long) switch_epoch_time_now(NULL) + (long) exptime + 60, + agent, from_user, guess_ip4, profile->name, mod_sofia_globals.hostname, network_ip, network_port_c, username, realm, + mwi_user, mwi_host, guess_ip4, mod_sofia_globals.hostname); + } else { + sql = switch_mprintf("update sip_registrations set expires = %ld where sip_user='%q' and sip_host='%q' and contact='%q'", (long) switch_epoch_time_now(NULL) + (long) exptime + 60, to_user, reg_host, contact_str); + } + if (sql) { sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); } - if (sofia_reg_reg_count(profile, to_user, reg_host) == 1) { + if (!update_registration && sofia_reg_reg_count(profile, to_user, reg_host) == 1) { sql = switch_mprintf("delete from sip_presence where sip_user='%q' and sip_host='%q' and profile_name='%q' and open_closed='closed'", to_user, reg_host, profile->name); if (mod_sofia_globals.debug_presence > 0) { @@ -1563,7 +1608,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); switch_event_fire(&event); } -#else + if (sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER) || (reg_count == 1 && sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER))) { @@ -1600,6 +1645,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand (sip && sip->sip_user_agent) ? sip->sip_user_agent->g_string : "unknown"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "Unregistered"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-source", "register"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); switch_event_fire(&event); } @@ -1628,9 +1674,10 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand if (delete_subs) { if (multi_reg_contact) { sql = - switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, sub_host, contact_str); + switch_mprintf("update sip_subscriptions set expires=%ld where sip_user='%q' and sip_host='%q' and contact='%q'", + (long) switch_epoch_time_now(NULL), to_user, sub_host, contact_str); } else { - sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", call_id); + sql = switch_mprintf("update sip_subscriptions set expires=%ld where call_id='%q'", (long) switch_epoch_time_now(NULL), call_id); } sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); @@ -1648,7 +1695,8 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand switch_safe_free(icontact); } else { if (delete_subs) { - if ((sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host))) { + if ((sql = switch_mprintf("update sip_subscriptions set expires=%ld where sip_user='%q' and sip_host='%q'", + (long) switch_epoch_time_now(NULL), to_user, sub_host))) { sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); } } @@ -1681,7 +1729,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand (reg_count == 1 && sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER))) { if (switch_event_create(&s_mwi_event, SWITCH_EVENT_MESSAGE_QUERY) == SWITCH_STATUS_SUCCESS) { switch_event_add_header(s_mwi_event, SWITCH_STACK_BOTTOM, "Message-Account", "sip:%s@%s", mwi_user, mwi_host); - switch_event_add_header_string(s_mwi_event, SWITCH_STACK_BOTTOM, "VM-Sofia-Profile", profile->name); + switch_event_add_header_string(s_mwi_event, SWITCH_STACK_BOTTOM, "VM-Sofia-Pofile", profile->name); switch_event_add_header_string(s_mwi_event, SWITCH_STACK_BOTTOM, "VM-Call-ID", call_id); } } @@ -1697,6 +1745,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host); switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, sub_host); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence"); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "presence-source", "register"); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); switch_event_fire(&s_event); } @@ -1704,6 +1753,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "presence-source", "register"); switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", "unknown"); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", "Registered"); @@ -1774,10 +1824,6 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand switch_event_fire(&s_mwi_event); } - if (contact && *contact_str && sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE_SYLANTRO)) { - sofia_sla_handle_register(nua, profile, sip, de, exptime, contact_str); - } - switch_goto_int(r, 1, end); } @@ -2098,7 +2144,7 @@ void sofia_reg_handle_sip_r_challenge(int status, switch_event_create(&locate_params, SWITCH_EVENT_REQUEST_PARAMS); switch_assert(locate_params); - switch_event_add_header_string(locate_params, SWITCH_STACK_BOTTOM, "Action", "reverse-auth-lookup"); + switch_event_add_header_string(locate_params, SWITCH_STACK_BOTTOM, "action", "reverse-auth-lookup"); if (switch_xml_locate_user_merged("id", sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, NULL, &x_user, locate_params) == SWITCH_STATUS_SUCCESS) { @@ -2626,8 +2672,7 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, switch_safe_free(input2); skip_auth: - - if (first && ret == AUTH_OK) { + if (first && (ret == AUTH_OK || ret == AUTH_RENEWED)) { if (v_event) { switch_event_create_plain(v_event, SWITCH_EVENT_REQUEST_PARAMS); } @@ -2753,6 +2798,9 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, switch_assert(sql != NULL); sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); switch_safe_free(sql); + + if (ret == AUTH_OK) + ret = AUTH_RENEWED; } switch_event_destroy(¶ms); @@ -2772,7 +2820,7 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, switch_safe_free(response); if (reg_count && !*reg_count) { - if (ret == AUTH_OK) { + if ((ret == AUTH_OK || ret == AUTH_RENEWED)) { if (ncl) { *reg_count = ncl; } else { diff --git a/src/mod/endpoints/mod_sofia/sofia_sla.c b/src/mod/endpoints/mod_sofia/sofia_sla.c deleted file mode 100644 index 3dcc455d29..0000000000 --- a/src/mod/endpoints/mod_sofia/sofia_sla.c +++ /dev/null @@ -1,413 +0,0 @@ -/* - * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005-2011, Anthony Minessale II - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * - * The Initial Developer of the Original Code is - * Anthony Minessale II - * Portions created by the Initial Developer are Copyright (C) - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Anthony Minessale II - * Ken Rice, Asteria Solutions Group, Inc - * Paul D. Tinsley - * Bret McDanel - * Brian West - * - * sofia_sla.c -- SOFIA SIP Endpoint (support for shared line appearance) - * This file (and calls into it) developed by Matthew T Kaufman - * - */ -#include "mod_sofia.h" - -static int sofia_sla_sub_callback(void *pArg, int argc, char **argv, char **columnNames); - -struct sla_helper { - char call_id[1024]; -}; - -static int get_call_id_callback(void *pArg, int argc, char **argv, char **columnNames) -{ - struct sla_helper *sh = (struct sla_helper *) pArg; - - switch_set_string(sh->call_id, argv[0]); - return 0; -} - -int sofia_sla_supported(sip_t const *sip) -{ - if (sip && sip->sip_user_agent && sip->sip_user_agent->g_string) { - const char *ua = sip->sip_user_agent->g_string; - - if (switch_stristr("polycom", ua)) { - return 1; - } - - if (switch_stristr("snom", ua)) { - return 1; - } - - } - - return 0; -} - - -void sofia_sla_handle_register(nua_t *nua, sofia_profile_t *profile, sip_t const *sip, - sofia_dispatch_event_t *de, long exptime, const char *full_contact) -{ - nua_handle_t *nh = NULL; - char exp_str[256] = ""; - char my_contact[256] = ""; - char *sql; - struct sla_helper sh = { {0} }; - char *contact_str = sofia_glue_strip_uri(full_contact); - sofia_transport_t transport = sofia_glue_url2transport(sip->sip_contact->m_url); - char network_ip[80]; - int network_port = 0; - sofia_destination_t *dst; - char *route_uri = NULL; - char port_str[25] = ""; - nua_handle_t *fnh = NULL; - - sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port); - - sql = switch_mprintf("select call_id from sip_shared_appearance_dialogs where hostname='%q' and profile_name='%q' and contact_str='%q'", - mod_sofia_globals.hostname, profile->name, contact_str); - sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, get_call_id_callback, &sh); - - free(sql); - - if (*sh.call_id) { - if ((nh = nua_handle_by_call_id(profile->nua, sh.call_id))) { - fnh = nh; - } else { - if ((sql = switch_mprintf("delete from sip_shared_appearance_dialogs where hostname='%q' and profile_name='%q' and contact_str='%q'", - mod_sofia_globals.hostname, profile->name, contact_str))) { - sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE); - } - } - } - - if (!nh) { - nh = nua_handle(nua, NULL, NUTAG_URL(sip->sip_contact->m_url), TAG_NULL()); - } - - nua_handle_bind(nh, &mod_sofia_globals.keep_private); - - switch_snprintf(exp_str, sizeof(exp_str), "%ld", exptime + 30); - - switch_snprintf(port_str, sizeof(port_str), ":%ld", sofia_glue_transport_has_tls(transport) ? profile->tls_sip_port : profile->sip_port); - - if (sofia_glue_check_nat(profile, network_ip)) { - switch_snprintf(my_contact, sizeof(my_contact), ";expires=%s", profile->sla_contact, - profile->extsipip, port_str, sofia_glue_transport2str(transport), exp_str); - } else { - switch_snprintf(my_contact, sizeof(my_contact), ";expires=%s", profile->sla_contact, - profile->sipip, port_str, sofia_glue_transport2str(transport), exp_str); - } - - dst = sofia_glue_get_destination((char *) full_contact); - - if (dst->route_uri) { - route_uri = sofia_glue_strip_uri(dst->route_uri); - } - - nua_subscribe(nh, - TAG_IF(dst->route_uri, NUTAG_PROXY(route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), - SIPTAG_TO(sip->sip_to), - SIPTAG_FROM(sip->sip_to), - SIPTAG_CONTACT_STR(my_contact), - SIPTAG_EXPIRES_STR(exp_str), - SIPTAG_EVENT_STR("dialog;sla;include-session-description"), SIPTAG_ACCEPT_STR("application/dialog-info+xml"), TAG_NULL()); - - - if (fnh) { - nua_handle_unref(fnh); - } - - sofia_glue_free_destination(dst); - - free(contact_str); -} - -void sofia_sla_handle_sip_i_publish(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip, - sofia_dispatch_event_t *de, tagi_t tags[]) -{ - /* at present there's no SLA versions that we deal with that do publish. to be safe, we say "OK" */ - nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END()); -} - -void sofia_sla_handle_sip_i_subscribe(nua_t *nua, const char *contact_str, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip, - sofia_dispatch_event_t *de, tagi_t tags[]) -{ - char *aor = NULL; - char *subscriber = NULL; - char *sql = NULL; - char *route_uri = NULL; - char *sla_contact = NULL; - char network_ip[80]; - int network_port = 0; - char port_str[25] = ""; - - sofia_transport_t transport = sofia_glue_url2transport(sip->sip_contact->m_url); - - sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port); - /* - * XXX MTK FIXME - we don't look at the tag to see if NUTAG_SUBSTATE(nua_substate_terminated) or - * a Subscription-State header with state "terminated" and/or expiration of 0. So we never forget - * about them here. - * likewise, we also don't have a hook against nua_r_notify events, so we can't see nua_substate_terminated there. - */ - - /* - * extracting AOR is weird... - * the From is the main extension, not the third-party one... - * and the contact has the phone's own network address, not the AOR address - * so we do what openser's pua_bla does and... - */ - - /* We always store the AOR as the sipip and not the request so SLA works with NAT inside out */ - aor = switch_mprintf("sip:%s@%s", sip->sip_contact->m_url->url_user, profile->sipip); - - /* - * ok, and now that we HAVE the AOR, we REALLY should go check in the XML config and see if this particular - * extension is set up to have shared appearances managed. right now it is all-or-nothing on the profile, - * which won't be sufficient for real life. FIXME XXX MTK - */ - - /* then the subscriber is the user at their network location... this is arguably the wrong way, but works so far... */ - - subscriber = switch_mprintf("sip:%s@%s;transport=%s", sip->sip_from->a_url->url_user, - sip->sip_contact->m_url->url_host, sofia_glue_transport2str(transport)); - - if ((sql = - switch_mprintf("delete from sip_shared_appearance_subscriptions where subscriber='%q' and profile_name='%q' and hostname='%q'", - subscriber, profile->name, mod_sofia_globals.hostname))) { - sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE); - } - - if ((sql = - switch_mprintf("insert into sip_shared_appearance_subscriptions (subscriber, call_id, aor, profile_name, hostname, contact_str, network_ip) " - "values ('%q','%q','%q','%q','%q','%q','%q')", - subscriber, sip->sip_call_id->i_id, aor, profile->name, mod_sofia_globals.hostname, contact_str, network_ip))) { - sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE); - } - - if (strstr(contact_str, ";fs_nat")) { - char *p; - route_uri = sofia_glue_get_url_from_contact((char *) contact_str, 1); - if ((p = strstr(contact_str, ";fs_"))) { - *p = '\0'; - } - } - - if (route_uri) { - char *p; - - while (route_uri && *route_uri && (*route_uri == '<' || *route_uri == ' ')) { - route_uri++; - } - if ((p = strchr(route_uri, '>'))) { - *p++ = '\0'; - } - } - - switch_snprintf(port_str, sizeof(port_str), ":%ld", sofia_glue_transport_has_tls(transport) ? profile->tls_sip_port : profile->sip_port); - - if (sofia_glue_check_nat(profile, network_ip)) { - sla_contact = switch_mprintf("", profile->sla_contact, profile->extsipip, port_str, sofia_glue_transport2str(transport)); - } else { - sla_contact = switch_mprintf("", profile->sla_contact, profile->sipip, port_str, sofia_glue_transport2str(transport)); - } - - nua_respond(nh, SIP_202_ACCEPTED, SIPTAG_CONTACT_STR(sla_contact), NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_IF(route_uri, NUTAG_PROXY(route_uri)), SIPTAG_SUBSCRIPTION_STATE_STR("active;expires=300"), /* you thought the OTHER time was fake... need delta here FIXME XXX MTK */ - SIPTAG_EXPIRES_STR("300"), /* likewise, totally fake - FIXME XXX MTK */ - /* sofia_presence says something about needing TAG_IF(sticky, NUTAG_PROXY(sticky)) for NAT stuff? */ - TAG_END()); - - switch_safe_free(aor); - switch_safe_free(subscriber); - switch_safe_free(route_uri); - switch_safe_free(sla_contact); - switch_safe_free(sql); -} - -struct sla_notify_helper { - sofia_profile_t *profile; - char *payload; -}; - -void sofia_sla_handle_sip_r_subscribe(int status, - char const *phrase, - nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip, - sofia_dispatch_event_t *de, - tagi_t tags[]) -{ - if (status >= 300) { - nua_handle_destroy(nh); - sofia_private_free(sofia_private); - } else { - char *full_contact = sip_header_as_string(nua_handle_home(nh), (void *) sip->sip_contact); - time_t expires = switch_epoch_time_now(NULL); - char *sql; - char *contact_str = sofia_glue_strip_uri(full_contact); - - if (sip && sip->sip_expires) { - expires += sip->sip_expires->ex_delta + 30; - } - - if ((sql = switch_mprintf("insert into sip_shared_appearance_dialogs (profile_name, hostname, contact_str, call_id, expires) " - "values ('%q','%q','%q','%q','%ld')", - profile->name, mod_sofia_globals.hostname, contact_str, sip->sip_call_id->i_id, (long) expires))) { - sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE); - } - - free(contact_str); - } -} - -void sofia_sla_handle_sip_i_notify(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip, - sofia_dispatch_event_t *de, tagi_t tags[]) -{ - char *sql = NULL; - struct sla_notify_helper helper; - char *aor = NULL; - char *contact = NULL; - sofia_transport_t transport = sofia_glue_url2transport(sip->sip_contact->m_url); - - /* - * things we know we don't do: - * draft-anil-sipping-bla says we should look and see if the specific appearance is in use and if it is - * return an error for the i_notify, to handle the initial line-seize for dialing out case. - * to do that we would need to really track all the appearances *and* override sofia's autoresponder for i_notify - * because at this point, it already sent the 200 for us. - * and we simply don't track all the appearance status by decoding the XML payload out and recording that in - * an SQL line appearance database yet. we'll need to do that in order to do the above, and in order to make - * interoperation possible between devices that disagree on the dialog xml payload OR don't even do it that - * way and instead use things like call-info/line-seize events like the old Broadsoft spec. - * instead we cheat and just reflect the entire payload back to the subscribers (who, because we don't - * yet check each AOR as it comes in to see if it is to be managed, is more subscribers than we probably - * should have). for the current prototype stage, this works ok anyway. - * and because we don't parse the XML, we even reflect it right back to the notifier/sender (which is called - * "target" in the payload XML, of course). - * also because we don't track on a per-appearance basis, there IS NOT a hook back from sofia_glue to add - * an appearance index to the outbound invite for the "next free appearance". this can lead to race - * conditions where a call shows up on slightly different line key numbers at different phones, making - * "pick up on line X" meaningless if such a race occurs. again, it is a prototype. we can fix it later. - */ - - - /* the dispatcher calls us just because it is aimed at us, so check to see if it is dialog;sla at the very least... */ - - if ((!sip->sip_event) - || (strcasecmp(sip->sip_event->o_type, "dialog")) - || !msg_params_find(sip->sip_event->o_params, "sla")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "sent to sla-agent but not dialog;sla\n"); - return; - } - - /* calculate the AOR we're trying to tell people about. should probably double-check before derferencing XXX MTK */ - /* We always store the AOR as the sipip and not the request so SLA works with NAT inside out */ - aor = switch_mprintf("sip:%s@%s", sip->sip_to->a_url->url_user, profile->sipip); - - /* this isn't sufficient because on things like the polycom, the subscriber is the 'main' ext number, but the - * 'main' ext number isn't in ANY of the headers they send us in the notify. of course. - * as a side effect, the subscriber<>'%q' below isn't sufficient to prevent reflecting the event back - * at a phone that has the ext # != third-party#. see above, can only fix by parsing the XML for the 'target' - * so we don't reflect it back at anyone who is the "boss" config, but we do reflect it back at the "secretary" - * config. if that breaks the phone, just set them all up as the "boss" config where ext#==third-party# - */ - contact = switch_mprintf("sip:%s@%s;transport=%s", sip->sip_contact->m_url->url_user, - sip->sip_contact->m_url->url_host, sofia_glue_transport2str(transport)); - - if (sip->sip_payload && sip->sip_payload->pl_data) { - sql = switch_mprintf("select subscriber,call_id,aor,profile_name,hostname,contact_str,network_ip from sip_shared_appearance_subscriptions where " - "aor='%q' and profile_name='%q' and hostname='%q'", aor, profile->name, mod_sofia_globals.hostname); - - helper.profile = profile; - helper.payload = sip->sip_payload->pl_data; /* could just send the WHOLE payload. you'd get the type that way. */ - - /* which mutex if any is correct to hold in this callback? XXX MTK FIXME */ - sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_sla_sub_callback, &helper); - - switch_safe_free(sql); - switch_safe_free(aor); - switch_safe_free(contact); - } -} - -static int sofia_sla_sub_callback(void *pArg, int argc, char **argv, char **columnNames) -{ - struct sla_notify_helper *helper = pArg; - /* char *subscriber = argv[0]; */ - char *call_id = argv[1]; - /* char *aor = argv[2]; */ - /* char *profile_name = argv[3]; */ - /* char *hostname = argv[4]; */ - char *contact_str = argv[5]; - char *network_ip = argv[6]; - nua_handle_t *nh; - char *route_uri = NULL; - char *xml_fixup = NULL; - char *fixup = NULL; - nh = nua_handle_by_call_id(helper->profile->nua, call_id); /* that's all you need to find the subscription's nh */ - - if (nh) { - - if (strstr(contact_str, ";fs_nat")) { - char *p; - route_uri = sofia_glue_get_url_from_contact(contact_str, 1); - if ((p = strstr(contact_str, ";fs_"))) { - *p = '\0'; - } - } - - if (route_uri) { - char *p; - - while (route_uri && *route_uri && (*route_uri == '<' || *route_uri == ' ')) { - route_uri++; - } - if ((p = strchr(route_uri, '>'))) { - *p++ = '\0'; - } - } - - if (helper->profile->extsipip) { - if (sofia_glue_check_nat(helper->profile, network_ip)) { - fixup = switch_string_replace(helper->payload, helper->profile->sipip, helper->profile->extsipip); - } else { - fixup = switch_string_replace(helper->payload, helper->profile->extsipip, helper->profile->sipip); - } - xml_fixup = fixup; - } else { - xml_fixup = helper->payload; - } - - nua_notify(nh, SIPTAG_SUBSCRIPTION_STATE_STR("active;expires=300"), /* XXX MTK FIXME - this is totally fake calculation */ - TAG_IF(route_uri, NUTAG_PROXY(route_uri)), SIPTAG_CONTENT_TYPE_STR("application/dialog-info+xml"), /* could've just kept the type from the payload */ - SIPTAG_PAYLOAD_STR(xml_fixup), TAG_END()); - switch_safe_free(route_uri); - if (fixup && fixup != helper->payload) { - free(fixup); - } - nua_handle_unref(nh); - } - return 0; -} diff --git a/src/mod/event_handlers/mod_cdr_sqlite/mod_cdr_sqlite.c b/src/mod/event_handlers/mod_cdr_sqlite/mod_cdr_sqlite.c index abdb8101f6..73fe4109e7 100644 --- a/src/mod/event_handlers/mod_cdr_sqlite/mod_cdr_sqlite.c +++ b/src/mod/event_handlers/mod_cdr_sqlite/mod_cdr_sqlite.c @@ -164,6 +164,10 @@ static switch_status_t my_on_reporting(switch_core_session_t *session) write_cdr(sql); switch_safe_free(sql); + if (expanded_vars != template_str) { + switch_safe_free(expanded_vars); + } + return status; } diff --git a/src/mod/event_handlers/mod_erlang_event/handle_msg.c b/src/mod/event_handlers/mod_erlang_event/handle_msg.c index 87f91fc51b..2f45ea6203 100644 --- a/src/mod/event_handlers/mod_erlang_event/handle_msg.c +++ b/src/mod/event_handlers/mod_erlang_event/handle_msg.c @@ -26,6 +26,8 @@ * Anthony Minessale II * Andrew Thompson * Rob Charlton + * Darren Schreiber + * Mike Jerris * * * handle_msg.c -- handle messages received from erlang nodes @@ -590,13 +592,29 @@ static switch_status_t handle_msg_session_setevent(listener_t *listener, erlang_ static switch_status_t handle_msg_api(listener_t *listener, erlang_msg * msg, int arity, ei_x_buff * buf, ei_x_buff * rbuf) { char api_cmd[MAXATOMLEN]; - char arg[1024]; - if (arity < 3 || ei_decode_atom(buf->buff, &buf->index, api_cmd) || ei_decode_string(buf->buff, &buf->index, arg)) { - ei_x_encode_tuple_header(rbuf, 2); - ei_x_encode_atom(rbuf, "error"); - ei_x_encode_atom(rbuf, "badarg"); - return SWITCH_STATUS_SUCCESS; - } else { + int type; + int size; + char *arg; + switch_bool_t fail = SWITCH_FALSE; + + if (arity < 3) { + fail = SWITCH_TRUE; + } + + ei_get_type(buf->buff, &buf->index, &type, &size); + + if ((size > (sizeof(api_cmd) - 1)) || ei_decode_atom(buf->buff, &buf->index, api_cmd)) { + fail = SWITCH_TRUE; + } + + ei_get_type(buf->buff, &buf->index, &type, &size); + arg = malloc(size + 1); + + if (ei_decode_string(buf->buff, &buf->index, arg)) { + fail = SWITCH_TRUE; + } + + if (!fail) { struct api_command_struct acs = { 0 }; acs.listener = listener; acs.api_cmd = api_cmd; @@ -604,8 +622,17 @@ static switch_status_t handle_msg_api(listener_t *listener, erlang_msg * msg, in acs.bg = 0; acs.pid = msg->from; api_exec(NULL, (void *) &acs); + + switch_safe_free(arg); + /* don't reply */ return SWITCH_STATUS_FALSE; + } else { + ei_x_encode_tuple_header(rbuf, 2); + ei_x_encode_atom(rbuf, "error"); + ei_x_encode_atom(rbuf, "badarg"); + return SWITCH_STATUS_SUCCESS; + } } @@ -670,18 +697,38 @@ static switch_status_t handle_msg_sendevent(listener_t *listener, int arity, ei_ if ((strlen(esname) && switch_event_create_subclass(&event, etype, esname) == SWITCH_STATUS_SUCCESS) || switch_event_create(&event, etype) == SWITCH_STATUS_SUCCESS) { char key[1024]; - char value[1024]; + char *value; + int type; + int size; int i = 0; switch_bool_t fail = SWITCH_FALSE; while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity) && arity == 2) { i++; - if (ei_decode_string(buf->buff, &buf->index, key) || ei_decode_string(buf->buff, &buf->index, value)) { + + ei_get_type(buf->buff, &buf->index, &type, &size); + + if ((size > (sizeof(key) - 1)) || ei_decode_string(buf->buff, &buf->index, key)) { fail = SWITCH_TRUE; break; } - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, key, value); + ei_get_type(buf->buff, &buf->index, &type, &size); + value = malloc(size + 1); + + if (ei_decode_string(buf->buff, &buf->index, value)) { + fail = SWITCH_TRUE; + break; + } + + if (!fail && !strcmp(key, "body")) { + switch_safe_free(event->body); + event->body = value; + } else if (!fail) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, key, value); + } + + /* Do not free malloc here! The above commands utilize the raw allocated memory and skip any copying/duplication. Faster. */ } if (headerlength != i || fail) { @@ -715,16 +762,32 @@ static switch_status_t handle_msg_sendmsg(listener_t *listener, int arity, ei_x_ if (switch_event_create(&event, SWITCH_EVENT_SEND_MESSAGE) == SWITCH_STATUS_SUCCESS) { char key[1024]; - char value[1024]; + char *value; + int type; + int size; int i = 0; switch_bool_t fail = SWITCH_FALSE; + while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity) && arity == 2) { i++; - if (ei_decode_string(buf->buff, &buf->index, key) || ei_decode_string(buf->buff, &buf->index, value)) { + ei_get_type(buf->buff, &buf->index, &type, &size); + + if ((size > (sizeof(key) - 1)) || ei_decode_string(buf->buff, &buf->index, key)) { fail = SWITCH_TRUE; break; } - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, key, value); + + ei_get_type(buf->buff, &buf->index, &type, &size); + value = malloc(size + 1); + + if (ei_decode_string(buf->buff, &buf->index, value)) { + fail = SWITCH_TRUE; + break; + } + + if (!fail) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, key, value); + } } if (headerlength != i || fail) { diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index 92e30ecfb6..15a60f447a 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -389,6 +389,7 @@ static switch_xml_t erlang_fetch(const char *sectionstr, const char *tag_name, c if (!ptr->listener) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NULL pointer binding!\n"); + switch_thread_rwlock_unlock(globals.bindings_rwlock); goto cleanup; /* our pointer is trash */ } @@ -1818,7 +1819,7 @@ SWITCH_MODULE_RUNTIME_FUNCTION(mod_erlang_event_runtime) #else errno = 0; #endif - if ((clientfd = ei_accept_tmo(&ec, (int) listen_list.sockfd, &conn, 100)) == ERL_ERROR) { + if ((clientfd = ei_accept_tmo(&ec, (int) listen_list.sockfd, &conn, 500)) == ERL_ERROR) { if (prefs.done) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting Down\n"); } else if (erl_errno == ETIMEDOUT) { diff --git a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c index f6ea4735ce..d35488d235 100644 --- a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c +++ b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c @@ -94,6 +94,7 @@ struct listener { char remote_ip[50]; switch_port_t remote_port; switch_event_t *filters; + time_t linger_timeout; struct listener *next; }; @@ -1095,7 +1096,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_event_socket_load) static switch_status_t read_packet(listener_t *listener, switch_event_t **event, uint32_t timeout) { switch_size_t mlen, bytes = 0; - char mbuf[2048] = ""; + char *mbuf = NULL; char buf[1024] = ""; switch_size_t len; switch_status_t status = SWITCH_STATUS_SUCCESS; @@ -1105,16 +1106,20 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event, void *pop; char *ptr; uint8_t crcount = 0; - uint32_t max_len = sizeof(mbuf); + uint32_t max_len = 10485760, block_len = 2048, buf_len = 0; switch_channel_t *channel = NULL; int clen = 0; *event = NULL; if (prefs.done) { - return SWITCH_STATUS_FALSE; + switch_goto_status(SWITCH_STATUS_FALSE, end); } + switch_zmalloc(mbuf, block_len); + switch_assert(mbuf); + buf_len = block_len; + start = switch_epoch_time_now(NULL); ptr = mbuf; @@ -1126,10 +1131,24 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event, uint8_t do_sleep = 1; mlen = 1; + if (bytes == buf_len - 1) { + char *tmp; + int pos; + + pos = (ptr - mbuf); + buf_len += block_len; + tmp = realloc(mbuf, buf_len); + switch_assert(tmp); + mbuf = tmp; + memset(mbuf + bytes, 0, buf_len - bytes); + ptr = (mbuf + pos); + + } + status = switch_socket_recv(listener->sock, ptr, &mlen); if (prefs.done || (!SWITCH_STATUS_IS_BREAK(status) && status != SWITCH_STATUS_SUCCESS)) { - return SWITCH_STATUS_FALSE; + switch_goto_status(SWITCH_STATUS_FALSE, end); } if (mlen) { @@ -1198,7 +1217,7 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event, if (prefs.done || (!SWITCH_STATUS_IS_BREAK(status) && status != SWITCH_STATUS_SUCCESS)) { free(body); - return SWITCH_STATUS_FALSE; + switch_goto_status(SWITCH_STATUS_FALSE, end); } /* @@ -1230,7 +1249,7 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event, elapsed = (uint32_t) (switch_epoch_time_now(NULL) - start); if (elapsed >= timeout) { switch_clear_flag_locked(listener, LFLAG_RUNNING); - return SWITCH_STATUS_FALSE; + switch_goto_status(SWITCH_STATUS_FALSE, end); } } @@ -1325,6 +1344,12 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event, } } + if (switch_test_flag(listener, LFLAG_HANDLE_DISCO) && switch_epoch_time_now(NULL) > listener->linger_timeout) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(listener->session), SWITCH_LOG_DEBUG, "linger timeout, closing socket\n"); + status = SWITCH_STATUS_FALSE; + break; + } + if (channel && switch_channel_down(channel) && !switch_test_flag(listener, LFLAG_HANDLE_DISCO)) { switch_set_flag_locked(listener, LFLAG_HANDLE_DISCO); if (switch_test_flag(listener, LFLAG_LINGER)) { @@ -1354,6 +1379,9 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event, } } + end: + + switch_safe_free(mbuf); return status; } @@ -2239,8 +2267,15 @@ static switch_status_t parse_command(listener_t *listener, switch_event_t **even } } else if (!strncasecmp(cmd, "linger", 6)) { if (listener->session) { + uint32_t linger_time = 600; /* sounds reasonable? */ + if (*(cmd+6) == ' ' && *(cmd+7)) { /*how long do you want to linger?*/ + linger_time = (uint32_t)atoi(cmd+7); + } + + /*do we need a mutex to update linger_timeout ?*/ + listener->linger_timeout = switch_epoch_time_now(NULL) + linger_time; switch_set_flag_locked(listener, LFLAG_LINGER); - switch_snprintf(reply, reply_len, "+OK will linger"); + switch_snprintf(reply, reply_len, "+OK will linger %d seconds", linger_time); } else { switch_snprintf(reply, reply_len, "-ERR not controlling a session"); } diff --git a/src/mod/event_handlers/mod_json_cdr/Makefile b/src/mod/event_handlers/mod_json_cdr/Makefile index d5043e017d..0620c7df63 100644 --- a/src/mod/event_handlers/mod_json_cdr/Makefile +++ b/src/mod/event_handlers/mod_json_cdr/Makefile @@ -1,6 +1,6 @@ json-c=json-c-0.9 BASE=../../../.. -WANT_CURL=yes + JSON_DIR=$(switch_srcdir)/libs/$(json-c) JSON_BUILDDIR=$(switch_builddir)/libs/$(json-c) diff --git a/src/mod/event_handlers/mod_json_cdr/mod_json_cdr.c b/src/mod/event_handlers/mod_json_cdr/mod_json_cdr.c index 636fcd9dba..aad224655c 100644 --- a/src/mod/event_handlers/mod_json_cdr/mod_json_cdr.c +++ b/src/mod/event_handlers/mod_json_cdr/mod_json_cdr.c @@ -32,7 +32,7 @@ */ #include #include -#include +#include #include #define MAX_URLS 20 @@ -72,6 +72,7 @@ static struct { int auth_scheme; switch_memory_pool_t *pool; switch_event_node_t *node; + int encode_values; } globals; SWITCH_MODULE_LOAD_FUNCTION(mod_json_cdr_load); @@ -249,24 +250,27 @@ static void set_json_chan_vars(struct json_object *json, switch_channel_t *chann for (; hi; hi = hi->next) { if (!zstr(hi->name) && !zstr(hi->value)) { - char *data; - switch_size_t dlen = strlen(hi->value) * 3; + char *data = hi->value; + if (globals.encode_values == ENCODING_DEFAULT) { + switch_size_t dlen = strlen(hi->value) * 3; - if ((data = malloc(dlen))) { - memset(data, 0, dlen); - switch_url_encode(hi->value, data, dlen); - - variable = json_object_new_string(data); - if (!is_error(variable)) { - json_object_object_add(json, hi->name, variable); + if ((data = malloc(dlen))) { + memset(data, 0, dlen); + switch_url_encode(hi->value, data, dlen); } - free(data); + } + + variable = json_object_new_string(data); + if (!is_error(variable)) { + json_object_object_add(json, hi->name, variable); + } + + if (data != hi->value) { + switch_safe_free(data); } } } switch_channel_variable_last(channel); - - return; } @@ -610,8 +614,8 @@ static switch_status_t my_on_reporting(switch_core_session_t *session) uint32_t cur_try; long httpRes; CURL *curl_handle = NULL; - struct curl_slist *headers = NULL; - struct curl_slist *slist = NULL; + switch_curl_slist_t *headers = NULL; + switch_curl_slist_t *slist = NULL; switch_channel_t *channel = switch_core_session_get_channel(session); switch_status_t status = SWITCH_STATUS_FALSE; int is_b; @@ -663,6 +667,9 @@ static switch_status_t my_on_reporting(switch_core_session_t *session) wrote = write(fd, json_text, (unsigned) strlen(json_text)); close(fd); fd = -1; + if(wrote < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error writing [%s]\n",path); + } } else { char ebuf[512] = { 0 }; #ifdef WIN32 @@ -681,7 +688,7 @@ static switch_status_t my_on_reporting(switch_core_session_t *session) /* try to post it to the web server */ if (globals.url_count) { char *destUrl = NULL; - curl_handle = curl_easy_init(); + curl_handle = switch_curl_easy_init(); if (globals.encode) { switch_size_t need_bytes = strlen(json_text) * 3; @@ -690,10 +697,10 @@ static switch_status_t my_on_reporting(switch_core_session_t *session) switch_assert(json_text_escaped); memset(json_text_escaped, 0, need_bytes); if (globals.encode == ENCODING_DEFAULT) { - headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded"); + headers = switch_curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded"); switch_url_encode(json_text, json_text_escaped, need_bytes); } else { - headers = curl_slist_append(headers, "Content-Type: application/x-www-form-base64-encoded"); + headers = switch_curl_slist_append(headers, "Content-Type: application/x-www-form-base64-encoded"); switch_b64_encode((unsigned char *) json_text, need_bytes / 3, (unsigned char *) json_text_escaped, need_bytes); } @@ -705,54 +712,55 @@ static switch_status_t my_on_reporting(switch_core_session_t *session) } } else { - headers = curl_slist_append(headers, "Content-Type: application/x-www-form-plaintext"); + headers = switch_curl_slist_append(headers, "Content-Type: application/json"); curl_json_text = (char *)json_text; } if (!zstr(globals.cred)) { - curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, globals.auth_scheme); - curl_easy_setopt(curl_handle, CURLOPT_USERPWD, globals.cred); + switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, globals.auth_scheme); + switch_curl_easy_setopt(curl_handle, CURLOPT_USERPWD, globals.cred); } - curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(curl_handle, CURLOPT_POST, 1); - curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, curl_json_text); - curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-json/1.0"); - curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, httpCallBack); + switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers); + switch_curl_easy_setopt(curl_handle, CURLOPT_POST, 1); + switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1); + switch_curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, curl_json_text); + switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-json/1.0"); + switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, httpCallBack); if (globals.disable100continue) { - slist = curl_slist_append(slist, "Expect:"); - curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, slist); + slist = switch_curl_slist_append(slist, "Expect:"); + switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, slist); } if (globals.ssl_cert_file) { - curl_easy_setopt(curl_handle, CURLOPT_SSLCERT, globals.ssl_cert_file); + switch_curl_easy_setopt(curl_handle, CURLOPT_SSLCERT, globals.ssl_cert_file); } if (globals.ssl_key_file) { - curl_easy_setopt(curl_handle, CURLOPT_SSLKEY, globals.ssl_key_file); + switch_curl_easy_setopt(curl_handle, CURLOPT_SSLKEY, globals.ssl_key_file); } if (globals.ssl_key_password) { - curl_easy_setopt(curl_handle, CURLOPT_SSLKEYPASSWD, globals.ssl_key_password); + switch_curl_easy_setopt(curl_handle, CURLOPT_SSLKEYPASSWD, globals.ssl_key_password); } if (globals.ssl_version) { if (!strcasecmp(globals.ssl_version, "SSLv3")) { - curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3); + switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3); } else if (!strcasecmp(globals.ssl_version, "TLSv1")) { - curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); + switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); } } if (globals.ssl_cacert_file) { - curl_easy_setopt(curl_handle, CURLOPT_CAINFO, globals.ssl_cacert_file); + switch_curl_easy_setopt(curl_handle, CURLOPT_CAINFO, globals.ssl_cacert_file); } /* these were used for testing, optionally they may be enabled if someone desires - curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 120); // tcp timeout - curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); // 302 recursion level + switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 120); // tcp timeout + switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); // 302 recursion level */ for (cur_try = 0; cur_try < globals.retries; cur_try++) { @@ -761,25 +769,25 @@ static switch_status_t my_on_reporting(switch_core_session_t *session) } destUrl = switch_mprintf("%s?uuid=%s", globals.urls[globals.url_index], switch_core_session_get_uuid(session)); - curl_easy_setopt(curl_handle, CURLOPT_URL, destUrl); + switch_curl_easy_setopt(curl_handle, CURLOPT_URL, destUrl); if (!strncasecmp(destUrl, "https", 5)) { - curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0); - curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0); + switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0); + switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0); } if (globals.enable_cacert_check) { - curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, TRUE); + switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, TRUE); } if (globals.enable_ssl_verifyhost) { - curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 2); + switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 2); } - curl_easy_perform(curl_handle); - curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes); + switch_curl_easy_perform(curl_handle); + switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes); switch_safe_free(destUrl); - if (httpRes == 200) { + if (httpRes >= 200 && httpRes < 300) { goto success; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Got error [%ld] posting to web server [%s]\n", @@ -792,9 +800,9 @@ static switch_status_t my_on_reporting(switch_core_session_t *session) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Retry will be with url [%s]\n", globals.urls[globals.url_index]); } } - curl_easy_cleanup(curl_handle); - curl_slist_free_all(headers); - curl_slist_free_all(slist); + switch_curl_easy_cleanup(curl_handle); + switch_curl_slist_free_all(headers); + switch_curl_slist_free_all(slist); slist = NULL; headers = NULL; curl_handle = NULL; @@ -816,6 +824,9 @@ static switch_status_t my_on_reporting(switch_core_session_t *session) wrote = write(fd, json_text, (unsigned) strlen(json_text)); close(fd); fd = -1; + if(wrote < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error writing [%s]\n",path); + } break; } else { char ebuf[512] = { 0 }; @@ -837,13 +848,13 @@ static switch_status_t my_on_reporting(switch_core_session_t *session) error: if (curl_handle) { - curl_easy_cleanup(curl_handle); + switch_curl_easy_cleanup(curl_handle); } if (headers) { - curl_slist_free_all(headers); + switch_curl_slist_free_all(headers); } if (slist) { - curl_slist_free_all(slist); + switch_curl_slist_free_all(slist); } if (curl_json_text != json_text) { switch_safe_free(curl_json_text); @@ -903,6 +914,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_json_cdr_load) globals.disable100continue = 0; globals.pool = pool; globals.auth_scheme = CURLAUTH_BASIC; + globals.encode_values = ENCODING_DEFAULT; switch_thread_rwlock_create(&globals.log_path_lock, pool); @@ -1002,6 +1014,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_json_cdr_load) } else if (!strcasecmp(val, "any")) { globals.auth_scheme = CURLAUTH_ANY; } + } else if (!strcasecmp(var, "encode-values") && !zstr(val)) { + globals.encode_values = switch_true(val) ? ENCODING_DEFAULT : ENCODING_NONE; } } diff --git a/src/mod/formats/mod_shout/Makefile b/src/mod/formats/mod_shout/Makefile index 7388bc0c67..d35d75a630 100644 --- a/src/mod/formats/mod_shout/Makefile +++ b/src/mod/formats/mod_shout/Makefile @@ -1,10 +1,8 @@ -LAME=lame-3.97 +LAME=lame-3.98.4 SHOUT=libshout-2.2.2 MPG123=mpg123-1.13.2 BASE=../../../.. -WANT_CURL=yes - LAME_DIR=$(switch_srcdir)/libs/$(LAME) SHOUT_DIR=$(switch_srcdir)/libs/$(SHOUT) MPG123_DIR=$(switch_srcdir)/libs/$(MPG123) diff --git a/src/mod/formats/mod_shout/mod_shout.c b/src/mod/formats/mod_shout/mod_shout.c index ea6912b193..e3c3764429 100644 --- a/src/mod/formats/mod_shout/mod_shout.c +++ b/src/mod/formats/mod_shout/mod_shout.c @@ -445,30 +445,30 @@ static size_t stream_callback(void *ptr, size_t size, size_t nmemb, void *data) #define MY_BLOCK_SIZE MY_BUF_LEN static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void *obj) { - CURL *curl_handle = NULL; - CURLcode cc; + switch_CURL *curl_handle = NULL; + switch_CURLcode cc; shout_context_t *context = (shout_context_t *) obj; switch_thread_rwlock_rdlock(context->rwlock); - curl_handle = curl_easy_init(); - curl_easy_setopt(curl_handle, CURLOPT_URL, context->stream_url); - curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); - curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10); - curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, stream_callback); - curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) context); - curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "FreeSWITCH(mod_shout)/1.0"); - curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1); - curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, 30); /* eventually timeout connect */ - curl_easy_setopt(curl_handle, CURLOPT_LOW_SPEED_LIMIT, 100); /* handle trickle connections */ - curl_easy_setopt(curl_handle, CURLOPT_LOW_SPEED_TIME, 30); - curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, context->curl_error_buff); - cc = curl_easy_perform(curl_handle); + curl_handle = switch_curl_easy_init(); + switch_curl_easy_setopt(curl_handle, CURLOPT_URL, context->stream_url); + switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); + switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10); + switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, stream_callback); + switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) context); + switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "FreeSWITCH(mod_shout)/1.0"); + switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1); + switch_curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, 30); /* eventually timeout connect */ + switch_curl_easy_setopt(curl_handle, CURLOPT_LOW_SPEED_LIMIT, 100); /* handle trickle connections */ + switch_curl_easy_setopt(curl_handle, CURLOPT_LOW_SPEED_TIME, 30); + switch_curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, context->curl_error_buff); + cc = switch_curl_easy_perform(curl_handle); if (cc && cc != CURLE_WRITE_ERROR) { /* write error is ok, we just exited from callback early */ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "CURL returned error:[%d] %s : %s [%s]\n", cc, curl_easy_strerror(cc), + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "CURL returned error:[%d] %s : %s [%s]\n", cc, switch_curl_easy_strerror(cc), context->curl_error_buff, context->stream_url); } - curl_easy_cleanup(curl_handle); + switch_curl_easy_cleanup(curl_handle); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Read Thread Done\n"); context->eof++; @@ -836,6 +836,11 @@ static switch_status_t shout_file_open(switch_file_handle_t *handle, const char switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening %s\n", path); goto error; } + if (!context->lame_ready) { + lame_init_params(context->gfp); + lame_print_config(context->gfp); + context->lame_ready = 1; + } } } @@ -1545,8 +1550,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_shout_load) supported_formats[0] = "shout"; supported_formats[1] = "mp3"; - switch_curl_init(); - /* connect my internal structure to the blank pointer passed to me */ *module_interface = switch_loadable_module_create_module_interface(pool, modname); file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE); @@ -1572,7 +1575,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_shout_load) SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_shout_shutdown) { - switch_curl_destroy(); mpg123_exit(); return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/formats/mod_shout/mod_shout.vcproj b/src/mod/formats/mod_shout/mod_shout.vcproj index 8d72d7833e..423784ee48 100644 --- a/src/mod/formats/mod_shout/mod_shout.vcproj +++ b/src/mod/formats/mod_shout/mod_shout.vcproj @@ -42,7 +42,7 @@ Disabled - ../../../../libs/curl/include;../../../../libs/lame-3.97/include;..\..\..\..\libs\win32\libshout;..\..\..\..\libs\libshout-2.2.2\include;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123;%(AdditionalIncludeDirectories) + ../../../../libs/curl/include;../../../../libs/lame-3.98.4/include;..\..\..\..\libs\win32\libshout;..\..\..\..\libs\libshout-2.2.2\include;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123;%(AdditionalIncludeDirectories) CURL_STATICLIB;%(PreprocessorDefinitions) true EnableFastChecks @@ -89,7 +89,7 @@ Disabled - ../../../../libs/curl/include;../../../../libs/lame-3.97/include;..\..\..\..\libs\win32\libshout;..\..\..\..\libs\libshout-2.2.2\include;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123;%(AdditionalIncludeDirectories) + ../../../../libs/curl/include;../../../../libs/lame-3.98.4/include;..\..\..\..\libs\win32\libshout;..\..\..\..\libs\libshout-2.2.2\include;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123;%(AdditionalIncludeDirectories) CURL_STATICLIB;%(PreprocessorDefinitions) true EnableFastChecks @@ -109,7 +109,7 @@ MaxSpeed true - ../../../../libs/curl/include;../../../../libs/lame-3.97/include;..\..\..\..\libs\win32\libshout;..\..\..\..\libs\libshout-2.2.2\include;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123;%(AdditionalIncludeDirectories) + ../../../../libs/curl/include;../../../../libs/lame-3.98.4/include;..\..\..\..\libs\win32\libshout;..\..\..\..\libs\libshout-2.2.2\include;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123;%(AdditionalIncludeDirectories) CURL_STATICLIB;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -133,7 +133,7 @@ MaxSpeed true - ../../../../libs/curl/include;../../../../libs/lame-3.97/include;..\..\..\..\libs\win32\libshout;..\..\..\..\libs\libshout-2.2.2\include;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123;%(AdditionalIncludeDirectories) + ../../../../libs/curl/include;../../../../libs/lame-3.98.4/include;..\..\..\..\libs\win32\libshout;..\..\..\..\libs\libshout-2.2.2\include;..\..\..\..\libs\mpg123\src;..\..\..\..\libs\win32\mpg123;%(AdditionalIncludeDirectories) CURL_STATICLIB;%(PreprocessorDefinitions) MultiThreadedDLL true diff --git a/src/mod/formats/mod_sndfile/mod_sndfile.c b/src/mod/formats/mod_sndfile/mod_sndfile.c index 5b011dccb2..b7e4dbfd6b 100644 --- a/src/mod/formats/mod_sndfile/mod_sndfile.c +++ b/src/mod/formats/mod_sndfile/mod_sndfile.c @@ -146,6 +146,9 @@ static switch_status_t sndfile_file_open(switch_file_handle_t *handle, const cha context->sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM; context->sfinfo.channels = 1; context->sfinfo.samplerate = 8000; + } else if (!strcmp(ext, "oga")) { + context->sfinfo.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS; + context->sfinfo.samplerate = handle->samplerate; } if ((mode & SFM_WRITE) && sf_format_check(&context->sfinfo) == 0) { diff --git a/src/mod/languages/mod_java/mod_java.i b/src/mod/languages/mod_java/mod_java.i index 82bf21bd81..42527fd541 100644 --- a/src/mod/languages/mod_java/mod_java.i +++ b/src/mod/languages/mod_java/mod_java.i @@ -1,5 +1,5 @@ %module freeswitch - +%include ../../../../swig_common.i /** insert the following includes into generated code so it compiles */ %{ #include "switch_cpp.h" diff --git a/src/mod/languages/mod_java/src/org/freeswitch/swig/EventConsumer.java b/src/mod/languages/mod_java/src/org/freeswitch/swig/EventConsumer.java index 3cefab5bf8..4fecb81e00 100644 --- a/src/mod/languages/mod_java/src/org/freeswitch/swig/EventConsumer.java +++ b/src/mod/languages/mod_java/src/org/freeswitch/swig/EventConsumer.java @@ -99,8 +99,8 @@ public class EventConsumer { return freeswitchJNI.EventConsumer_bind(swigCPtr, this, event_name, subclass_name); } - public Event pop(int block) { - long cPtr = freeswitchJNI.EventConsumer_pop(swigCPtr, this, block); + public Event pop(int block, int timeout) { + long cPtr = freeswitchJNI.EventConsumer_pop(swigCPtr, this, block, timeout); return (cPtr == 0) ? null : new Event(cPtr, true); } diff --git a/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitch.java b/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitch.java index ea825c9014..7d832dbea0 100644 --- a/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitch.java +++ b/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitch.java @@ -9,6 +9,14 @@ package org.freeswitch.swig; public class freeswitch { + public static void setGlobalVariable(String var_name, String var_val) { + freeswitchJNI.setGlobalVariable(var_name, var_val); + } + + public static String getGlobalVariable(String var_name) { + return freeswitchJNI.getGlobalVariable(var_name); + } + public static void consoleLog(String level_str, String msg) { freeswitchJNI.consoleLog(level_str, msg); } diff --git a/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitchJNI.java b/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitchJNI.java index fc74914d15..b574831098 100644 --- a/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitchJNI.java +++ b/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitchJNI.java @@ -9,6 +9,8 @@ package org.freeswitch.swig; class freeswitchJNI { + public final static native void setGlobalVariable(String jarg1, String jarg2); + public final static native String getGlobalVariable(String jarg1); public final static native void consoleLog(String jarg1, String jarg2); public final static native void consoleCleanLog(String jarg1); public final static native boolean email(String jarg1, String jarg2, String jarg3, String jarg4, String jarg5, String jarg6, String jarg7); @@ -82,7 +84,7 @@ class freeswitchJNI { public final static native long new_EventConsumer(String jarg1, String jarg2); public final static native void delete_EventConsumer(long jarg1); public final static native int EventConsumer_bind(long jarg1, EventConsumer jarg1_, String jarg2, String jarg3); - public final static native long EventConsumer_pop(long jarg1, EventConsumer jarg1_, int jarg2); + public final static native long EventConsumer_pop(long jarg1, EventConsumer jarg1_, int jarg2, int jarg3); public final static native void delete_CoreSession(long jarg1); public final static native void CoreSession_session_set(long jarg1, CoreSession jarg1_, long jarg2); public final static native long CoreSession_session_get(long jarg1, CoreSession jarg1_); diff --git a/src/mod/languages/mod_java/switch_swig_wrap.cpp b/src/mod/languages/mod_java/switch_swig_wrap.cpp index 5061dc46f6..c34420ea96 100644 --- a/src/mod/languages/mod_java/switch_swig_wrap.cpp +++ b/src/mod/languages/mod_java/switch_swig_wrap.cpp @@ -207,6 +207,48 @@ static void SWIGUNUSED SWIG_JavaThrowException(JNIEnv *jenv, SWIG_JavaExceptionC extern "C" { #endif +SWIGEXPORT void JNICALL Java_org_freeswitch_swig_freeswitchJNI_setGlobalVariable(JNIEnv *jenv, jclass jcls, jstring jarg1, jstring jarg2) { + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + + (void)jenv; + (void)jcls; + arg1 = 0; + if (jarg1) { + arg1 = (char *)jenv->GetStringUTFChars(jarg1, 0); + if (!arg1) return ; + } + arg2 = 0; + if (jarg2) { + arg2 = (char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2) return ; + } + setGlobalVariable(arg1,arg2); + if (arg1) jenv->ReleaseStringUTFChars(jarg1, (const char *)arg1); + if (arg2) jenv->ReleaseStringUTFChars(jarg2, (const char *)arg2); +} + + +SWIGEXPORT jstring JNICALL Java_org_freeswitch_swig_freeswitchJNI_getGlobalVariable(JNIEnv *jenv, jclass jcls, jstring jarg1) { + jstring jresult = 0 ; + char *arg1 = (char *) 0 ; + char *result = 0 ; + + (void)jenv; + (void)jcls; + arg1 = 0; + if (jarg1) { + arg1 = (char *)jenv->GetStringUTFChars(jarg1, 0); + if (!arg1) return 0; + } + result = (char *)getGlobalVariable(arg1); + if(result) jresult = jenv->NewStringUTF((const char *)result); + if (arg1) jenv->ReleaseStringUTFChars(jarg1, (const char *)arg1); + free(result); + return jresult; +} + + SWIGEXPORT void JNICALL Java_org_freeswitch_swig_freeswitchJNI_consoleLog(JNIEnv *jenv, jclass jcls, jstring jarg1, jstring jarg2) { char *arg1 = (char *) 0 ; char *arg2 = (char *) 0 ; @@ -1611,10 +1653,11 @@ SWIGEXPORT jint JNICALL Java_org_freeswitch_swig_freeswitchJNI_EventConsumer_1bi } -SWIGEXPORT jlong JNICALL Java_org_freeswitch_swig_freeswitchJNI_EventConsumer_1pop(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2) { +SWIGEXPORT jlong JNICALL Java_org_freeswitch_swig_freeswitchJNI_EventConsumer_1pop(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2, jint jarg3) { jlong jresult = 0 ; EventConsumer *arg1 = (EventConsumer *) 0 ; int arg2 = (int) 0 ; + int arg3 = (int) 0 ; Event *result = 0 ; (void)jenv; @@ -1622,7 +1665,8 @@ SWIGEXPORT jlong JNICALL Java_org_freeswitch_swig_freeswitchJNI_EventConsumer_1p (void)jarg1_; arg1 = *(EventConsumer **)&jarg1; arg2 = (int)jarg2; - result = (Event *)(arg1)->pop(arg2); + arg3 = (int)jarg3; + result = (Event *)(arg1)->pop(arg2,arg3); *(Event **)&jresult = result; return jresult; } diff --git a/src/mod/languages/mod_lua/freeswitch.i b/src/mod/languages/mod_lua/freeswitch.i index 25faa5a5df..ae2b468c77 100644 --- a/src/mod/languages/mod_lua/freeswitch.i +++ b/src/mod/languages/mod_lua/freeswitch.i @@ -1,4 +1,5 @@ %module freeswitch +%include ../../../../swig_common.i //%include "cstring.i" /** diff --git a/src/mod/languages/mod_lua/mod_lua.cpp b/src/mod/languages/mod_lua/mod_lua.cpp index a165795cb0..abeb847550 100644 --- a/src/mod/languages/mod_lua/mod_lua.cpp +++ b/src/mod/languages/mod_lua/mod_lua.cpp @@ -135,9 +135,14 @@ static int lua_parse_and_execute(lua_State * L, char *input_code) return 1; } + while(input_code && (*input_code == ' ' || *input_code == '\n' || *input_code == '\r')) input_code++; + if (*input_code == '~') { char *buff = input_code + 1; error = luaL_loadbuffer(L, buff, strlen(buff), "line") || docall(L, 0, 1, 0); //lua_pcall(L, 0, 0, 0); + } else if (!strncasecmp(input_code, "#!/lua", 6)) { + char *buff = input_code + 6; + error = luaL_loadbuffer(L, buff, strlen(buff), "line") || docall(L, 0, 1, 0); //lua_pcall(L, 0, 0, 0); } else { char *args = strchr(input_code, ' '); if (args) { diff --git a/src/mod/languages/mod_lua/mod_lua_wrap.cpp b/src/mod/languages/mod_lua/mod_lua_wrap.cpp index 3bb1ad5d71..5b1a0b65b3 100644 --- a/src/mod/languages/mod_lua/mod_lua_wrap.cpp +++ b/src/mod/languages/mod_lua/mod_lua_wrap.cpp @@ -1539,6 +1539,51 @@ typedef struct{} LANGUAGE_OBJ; #ifdef __cplusplus extern "C" { #endif +static int _wrap_setGlobalVariable(lua_State* L) { + int SWIG_arg = -1; + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + + SWIG_check_num_args("setGlobalVariable",2,2) + if(!lua_isstring(L,1)) SWIG_fail_arg("setGlobalVariable",1,"char *"); + if(!lua_isstring(L,2)) SWIG_fail_arg("setGlobalVariable",2,"char *"); + arg1 = (char *)lua_tostring(L, 1); + arg2 = (char *)lua_tostring(L, 2); + setGlobalVariable(arg1,arg2); + SWIG_arg=0; + + return SWIG_arg; + + if(0) SWIG_fail; + +fail: + lua_error(L); + return SWIG_arg; +} + + +static int _wrap_getGlobalVariable(lua_State* L) { + int SWIG_arg = -1; + char *arg1 = (char *) 0 ; + char *result = 0 ; + + SWIG_check_num_args("getGlobalVariable",1,1) + if(!lua_isstring(L,1)) SWIG_fail_arg("getGlobalVariable",1,"char *"); + arg1 = (char *)lua_tostring(L, 1); + result = (char *)getGlobalVariable(arg1); + SWIG_arg=0; + lua_pushstring(L,(const char*)result); SWIG_arg++; + free(result); + return SWIG_arg; + + if(0) SWIG_fail; + +fail: + lua_error(L); + return SWIG_arg; +} + + static int _wrap_consoleLog(lua_State* L) { int SWIG_arg = -1; char *arg1 = (char *) 0 ; @@ -3746,11 +3791,13 @@ static int _wrap_EventConsumer_pop(lua_State* L) { int SWIG_arg = -1; EventConsumer *arg1 = (EventConsumer *) 0 ; int arg2 = (int) 0 ; + int arg3 = (int) 0 ; Event *result = 0 ; - SWIG_check_num_args("pop",1,2) + SWIG_check_num_args("pop",1,3) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("pop",1,"EventConsumer *"); if(lua_gettop(L)>=2 && !lua_isnumber(L,2)) SWIG_fail_arg("pop",2,"int"); + if(lua_gettop(L)>=3 && !lua_isnumber(L,3)) SWIG_fail_arg("pop",3,"int"); if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_EventConsumer,0))){ SWIG_fail_ptr("EventConsumer_pop",1,SWIGTYPE_p_EventConsumer); @@ -3759,7 +3806,10 @@ static int _wrap_EventConsumer_pop(lua_State* L) { if(lua_gettop(L)>=2){ arg2 = (int)lua_tonumber(L, 2); } - result = (Event *)(arg1)->pop(arg2); + if(lua_gettop(L)>=3){ + arg3 = (int)lua_tonumber(L, 3); + } + result = (Event *)(arg1)->pop(arg2,arg3); SWIG_arg=0; SWIG_NewPointerObj(L,result,SWIGTYPE_p_Event,1); SWIG_arg++; return SWIG_arg; @@ -7642,6 +7692,8 @@ static swig_lua_class _wrap_class_LUA_Dbh = { "Dbh", &SWIGTYPE_p_LUA__Dbh,_wrap_ #endif static const struct luaL_reg swig_commands[] = { + { "setGlobalVariable", _wrap_setGlobalVariable}, + { "getGlobalVariable", _wrap_getGlobalVariable}, { "consoleLog", _wrap_consoleLog}, { "consoleCleanLog", _wrap_consoleCleanLog}, { "email", _wrap_email}, diff --git a/src/mod/languages/mod_managed/Makefile b/src/mod/languages/mod_managed/Makefile index 0ac49b44a8..ec44ff5131 100644 --- a/src/mod/languages/mod_managed/Makefile +++ b/src/mod/languages/mod_managed/Makefile @@ -1,6 +1,6 @@ -LOCAL_INSERT_CFLAGS= /usr/bin/pkg-config mono --cflags -LOCAL_INSERT_LDFLAGS= /usr/bin/pkg-config mono --libs -#MOD_CFLAGS=-D_REENTRANT -pthread -I/opt/mono-1.9/lib/pkgconfig/../../include/mono-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -lmono +LOCAL_INSERT_CFLAGS= /usr/bin/pkg-config mono-2 --cflags +LOCAL_INSERT_LDFLAGS= /usr/bin/pkg-config mono-2 --libs +#MOD_CFLAGS=-D_REENTRANT -pthread -I/usr/lib/mono -lmono BASE=../../../.. VERBOSE=1 include $(BASE)/build/modmake.rules diff --git a/src/mod/languages/mod_managed/freeswitch.i b/src/mod/languages/mod_managed/freeswitch.i index ffbdf9be0f..228afaa751 100644 --- a/src/mod/languages/mod_managed/freeswitch.i +++ b/src/mod/languages/mod_managed/freeswitch.i @@ -1,5 +1,7 @@ %module freeswitch +%include ../../../../swig_common.i + /** String fix - copied from csharphead.swg with fix for multiple appdomains **/ /* Must pass -DSWIG_CSHARP_NO_STRING_HELPER to swig */ @@ -8,7 +10,6 @@ /* Callback for returning strings to C# without leaking memory */ #ifndef _MANAGED -#include #include #include #include diff --git a/src/mod/languages/mod_managed/freeswitch_managed.h b/src/mod/languages/mod_managed/freeswitch_managed.h index 1d0b6a72b1..13ffe5d552 100644 --- a/src/mod/languages/mod_managed/freeswitch_managed.h +++ b/src/mod/languages/mod_managed/freeswitch_managed.h @@ -40,7 +40,6 @@ typedef void (*hangupFunction) (void); typedef char *(*inputFunction) (void *, switch_input_type_t); #ifndef _MANAGED -#include #include #include #include @@ -73,7 +72,7 @@ extern mod_managed_globals globals; #ifdef WIN32 #define RESULT_FREE(x) CoTaskMemFree(x) #else -#define RESULT_FREE(x) g_free(x) +#define RESULT_FREE(x) mono_free(x) #endif SWITCH_END_EXTERN_C diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx index cc6fa0fe57..7b192138cc 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx @@ -270,7 +270,6 @@ SWIGEXPORT void SWIGSTDCALL SWIGRegisterExceptionArgumentCallbacks_freeswitch( /* Callback for returning strings to C# without leaking memory */ #ifndef _MANAGED -#include #include #include #include @@ -1071,6 +1070,16 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE } +SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_TRANSFER_HISTORY_VARIABLE_get() { + char * jresult ; + char *result = 0 ; + + result = (char *)("transfer_history"); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE_get() { char * jresult ; char *result = 0 ; @@ -3838,6 +3847,35 @@ SWIGEXPORT unsigned short SWIGSTDCALL CSharp_switch_t38_options_t_local_port_get } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_t38_options_t_sdp_o_line_set(void * jarg1, char * jarg2) { + switch_t38_options_t *arg1 = (switch_t38_options_t *) 0 ; + char *arg2 = (char *) 0 ; + + arg1 = (switch_t38_options_t *)jarg1; + arg2 = (char *)jarg2; + { + if (arg2) { + arg1->sdp_o_line = (char const *) (new char[strlen((const char *)arg2)+1]); + strcpy((char *)arg1->sdp_o_line, (const char *)arg2); + } else { + arg1->sdp_o_line = 0; + } + } +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_t38_options_t_sdp_o_line_get(void * jarg1) { + char * jresult ; + switch_t38_options_t *arg1 = (switch_t38_options_t *) 0 ; + char *result = 0 ; + + arg1 = (switch_t38_options_t *)jarg1; + result = (char *) ((arg1)->sdp_o_line); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_t38_options_t() { void * jresult ; switch_t38_options_t *result = 0 ; @@ -5320,6 +5358,18 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_regex_set_var_callback(char * jarg1, c } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_regex_set_event_header_callback(char * jarg1, char * jarg2, void * jarg3) { + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + void *arg3 = (void *) 0 ; + + arg1 = (char *)jarg1; + arg2 = (char *)jarg2; + arg3 = (void *)jarg3; + switch_regex_set_event_header_callback((char const *)arg1,(char const *)arg2,arg3); +} + + SWIGEXPORT int SWIGSTDCALL CSharp_SWITCH_MAX_CORE_THREAD_SESSION_OBJS_get() { int jresult ; int result; @@ -6809,30 +6859,6 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_add_state_handler(void * jarg1) { } -SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_curl_count(void * jarg1) { - int jresult ; - int *arg1 = (int *) 0 ; - int result; - - arg1 = (int *)jarg1; - result = (int)switch_core_curl_count(arg1); - jresult = result; - return jresult; -} - - -SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_ssl_count(void * jarg1) { - int jresult ; - int *arg1 = (int *) 0 ; - int result; - - arg1 = (int *)jarg1; - result = (int)switch_core_ssl_count(arg1); - jresult = result; - return jresult; -} - - SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_remove_state_handler(void * jarg1) { switch_state_handler_table_t *arg1 = (switch_state_handler_table_t *) 0 ; @@ -6881,6 +6907,16 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_perform_new_memory_pool(void * jar } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_sync_clock() { + int jresult ; + int result; + + result = (int)switch_core_session_sync_clock(); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_perform_destroy_memory_pool(void * jarg1, char * jarg2, char * jarg3, int jarg4) { int jresult ; switch_memory_pool_t **arg1 = (switch_memory_pool_t **) 0 ; @@ -10240,6 +10276,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_chat_send(char * jarg1, void * jar } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_chat_deliver(char * jarg1, void * jarg2) { + int jresult ; + char *arg1 = (char *) 0 ; + switch_event_t **arg2 = (switch_event_t **) 0 ; + switch_status_t result; + + arg1 = (char *)jarg1; + arg2 = (switch_event_t **)jarg2; + result = (switch_status_t)switch_core_chat_deliver((char const *)arg1,arg2); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_preprocess_session(void * jarg1, char * jarg2) { int jresult ; switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; @@ -11072,6 +11122,28 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_switch_loadable_module_interface_applicatio } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_loadable_module_interface_chat_application_interface_set(void * jarg1, void * jarg2) { + switch_loadable_module_interface *arg1 = (switch_loadable_module_interface *) 0 ; + switch_chat_application_interface_t *arg2 = (switch_chat_application_interface_t *) 0 ; + + arg1 = (switch_loadable_module_interface *)jarg1; + arg2 = (switch_chat_application_interface_t *)jarg2; + if (arg1) (arg1)->chat_application_interface = arg2; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_loadable_module_interface_chat_application_interface_get(void * jarg1) { + void * jresult ; + switch_loadable_module_interface *arg1 = (switch_loadable_module_interface *) 0 ; + switch_chat_application_interface_t *result = 0 ; + + arg1 = (switch_loadable_module_interface *)jarg1; + result = (switch_chat_application_interface_t *) ((arg1)->chat_application_interface); + jresult = (void *)result; + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_loadable_module_interface_api_interface_set(void * jarg1, void * jarg2) { switch_loadable_module_interface *arg1 = (switch_loadable_module_interface *) 0 ; switch_api_interface_t *arg2 = (switch_api_interface_t *) 0 ; @@ -11481,6 +11553,34 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_switch_loadable_module_get_application_inte } +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_loadable_module_get_chat_application_interface(char * jarg1) { + void * jresult ; + char *arg1 = (char *) 0 ; + switch_chat_application_interface_t *result = 0 ; + + arg1 = (char *)jarg1; + result = (switch_chat_application_interface_t *)switch_loadable_module_get_chat_application_interface((char const *)arg1); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_execute_chat_app(void * jarg1, char * jarg2, char * jarg3) { + int jresult ; + switch_event_t *arg1 = (switch_event_t *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + switch_status_t result; + + arg1 = (switch_event_t *)jarg1; + arg2 = (char *)jarg2; + arg3 = (char *)jarg3; + result = (switch_status_t)switch_core_execute_chat_app(arg1,(char const *)arg2,(char const *)arg3); + jresult = result; + return jresult; +} + + SWIGEXPORT void * SWIGSTDCALL CSharp_switch_loadable_module_get_api_interface(char * jarg1) { void * jresult ; char *arg1 = (char *) 0 ; @@ -12497,6 +12597,22 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_is_number(char * jarg1) { } +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_find_parameter(char * jarg1, char * jarg2, void * jarg3) { + char * jresult ; + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + switch_memory_pool_t *arg3 = (switch_memory_pool_t *) 0 ; + char *result = 0 ; + + arg1 = (char *)jarg1; + arg2 = (char *)jarg2; + arg3 = (switch_memory_pool_t *)jarg3; + result = (char *)switch_find_parameter((char const *)arg1,(char const *)arg2,arg3); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_true(char * jarg1) { int jresult ; char *arg1 = (char *) 0 ; @@ -12791,6 +12907,20 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_clean_name_string(char * jarg1) { } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_safe_atoi(char * jarg1, int jarg2) { + int jresult ; + char *arg1 = (char *) 0 ; + int arg2 ; + int result; + + arg1 = (char *)jarg1; + arg2 = (int)jarg2; + result = (int)switch_safe_atoi((char const *)arg1,arg2); + jresult = result; + return jresult; +} + + SWIGEXPORT char * SWIGSTDCALL CSharp_switch_safe_strdup(char * jarg1) { char * jresult ; char *arg1 = (char *) 0 ; @@ -13471,6 +13601,38 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_split_user_domain(char * jarg1, void * } +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_uuid_str(char * jarg1, void * jarg2) { + char * jresult ; + char *arg1 = (char *) 0 ; + switch_size_t arg2 ; + switch_size_t *argp2 ; + char *result = 0 ; + + arg1 = (char *)jarg1; + argp2 = (switch_size_t *)jarg2; + if (!argp2) { + SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null switch_size_t", 0); + return 0; + } + arg2 = *argp2; + result = (char *)switch_uuid_str(arg1,arg2); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_format_number(char * jarg1) { + char * jresult ; + char *arg1 = (char *) 0 ; + char *result = 0 ; + + arg1 = (char *)jarg1; + result = (char *)switch_format_number((char const *)arg1); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_profile_node_t_var_set(void * jarg1, char * jarg2) { profile_node_t *arg1 = (profile_node_t *) 0 ; char *arg2 = (char *) 0 ; @@ -14456,6 +14618,96 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_switch_caller_profile_soft_get(void * jarg1 } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_caller_profile_uuid_str_set(void * jarg1, char * jarg2) { + switch_caller_profile *arg1 = (switch_caller_profile *) 0 ; + char *arg2 = (char *) 0 ; + + arg1 = (switch_caller_profile *)jarg1; + arg2 = (char *)jarg2; + { + if (arg1->uuid_str) delete [] arg1->uuid_str; + if (arg2) { + arg1->uuid_str = (char *) (new char[strlen((const char *)arg2)+1]); + strcpy((char *)arg1->uuid_str, (const char *)arg2); + } else { + arg1->uuid_str = 0; + } + } +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_caller_profile_uuid_str_get(void * jarg1) { + char * jresult ; + switch_caller_profile *arg1 = (switch_caller_profile *) 0 ; + char *result = 0 ; + + arg1 = (switch_caller_profile *)jarg1; + result = (char *) ((arg1)->uuid_str); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_caller_profile_clone_of_set(void * jarg1, char * jarg2) { + switch_caller_profile *arg1 = (switch_caller_profile *) 0 ; + char *arg2 = (char *) 0 ; + + arg1 = (switch_caller_profile *)jarg1; + arg2 = (char *)jarg2; + { + if (arg1->clone_of) delete [] arg1->clone_of; + if (arg2) { + arg1->clone_of = (char *) (new char[strlen((const char *)arg2)+1]); + strcpy((char *)arg1->clone_of, (const char *)arg2); + } else { + arg1->clone_of = 0; + } + } +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_caller_profile_clone_of_get(void * jarg1) { + char * jresult ; + switch_caller_profile *arg1 = (switch_caller_profile *) 0 ; + char *result = 0 ; + + arg1 = (switch_caller_profile *)jarg1; + result = (char *) ((arg1)->clone_of); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_caller_profile_transfer_source_set(void * jarg1, char * jarg2) { + switch_caller_profile *arg1 = (switch_caller_profile *) 0 ; + char *arg2 = (char *) 0 ; + + arg1 = (switch_caller_profile *)jarg1; + arg2 = (char *)jarg2; + { + if (arg1->transfer_source) delete [] arg1->transfer_source; + if (arg2) { + arg1->transfer_source = (char *) (new char[strlen((const char *)arg2)+1]); + strcpy((char *)arg1->transfer_source, (const char *)arg2); + } else { + arg1->transfer_source = 0; + } + } +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_caller_profile_transfer_source_get(void * jarg1) { + char * jresult ; + switch_caller_profile *arg1 = (switch_caller_profile *) 0 ; + char *result = 0 ; + + arg1 = (switch_caller_profile *)jarg1; + result = (char *) ((arg1)->transfer_source); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_caller_profile() { void * jresult ; switch_caller_profile *result = 0 ; @@ -22566,6 +22818,294 @@ SWIGEXPORT void SWIGSTDCALL CSharp_delete_switch_application_interface(void * ja } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_interface_name_set(void * jarg1, char * jarg2) { + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + char *arg2 = (char *) 0 ; + + arg1 = (switch_chat_application_interface *)jarg1; + arg2 = (char *)jarg2; + { + if (arg2) { + arg1->interface_name = (char const *) (new char[strlen((const char *)arg2)+1]); + strcpy((char *)arg1->interface_name, (const char *)arg2); + } else { + arg1->interface_name = 0; + } + } +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_chat_application_interface_interface_name_get(void * jarg1) { + char * jresult ; + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + char *result = 0 ; + + arg1 = (switch_chat_application_interface *)jarg1; + result = (char *) ((arg1)->interface_name); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_chat_application_function_set(void * jarg1, void * jarg2) { + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + switch_chat_application_function_t arg2 = (switch_chat_application_function_t) 0 ; + + arg1 = (switch_chat_application_interface *)jarg1; + arg2 = (switch_chat_application_function_t)jarg2; + if (arg1) (arg1)->chat_application_function = arg2; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_chat_application_interface_chat_application_function_get(void * jarg1) { + void * jresult ; + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + switch_chat_application_function_t result; + + arg1 = (switch_chat_application_interface *)jarg1; + result = (switch_chat_application_function_t) ((arg1)->chat_application_function); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_long_desc_set(void * jarg1, char * jarg2) { + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + char *arg2 = (char *) 0 ; + + arg1 = (switch_chat_application_interface *)jarg1; + arg2 = (char *)jarg2; + { + if (arg2) { + arg1->long_desc = (char const *) (new char[strlen((const char *)arg2)+1]); + strcpy((char *)arg1->long_desc, (const char *)arg2); + } else { + arg1->long_desc = 0; + } + } +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_chat_application_interface_long_desc_get(void * jarg1) { + char * jresult ; + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + char *result = 0 ; + + arg1 = (switch_chat_application_interface *)jarg1; + result = (char *) ((arg1)->long_desc); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_short_desc_set(void * jarg1, char * jarg2) { + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + char *arg2 = (char *) 0 ; + + arg1 = (switch_chat_application_interface *)jarg1; + arg2 = (char *)jarg2; + { + if (arg2) { + arg1->short_desc = (char const *) (new char[strlen((const char *)arg2)+1]); + strcpy((char *)arg1->short_desc, (const char *)arg2); + } else { + arg1->short_desc = 0; + } + } +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_chat_application_interface_short_desc_get(void * jarg1) { + char * jresult ; + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + char *result = 0 ; + + arg1 = (switch_chat_application_interface *)jarg1; + result = (char *) ((arg1)->short_desc); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_syntax_set(void * jarg1, char * jarg2) { + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + char *arg2 = (char *) 0 ; + + arg1 = (switch_chat_application_interface *)jarg1; + arg2 = (char *)jarg2; + { + if (arg2) { + arg1->syntax = (char const *) (new char[strlen((const char *)arg2)+1]); + strcpy((char *)arg1->syntax, (const char *)arg2); + } else { + arg1->syntax = 0; + } + } +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_chat_application_interface_syntax_get(void * jarg1) { + char * jresult ; + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + char *result = 0 ; + + arg1 = (switch_chat_application_interface *)jarg1; + result = (char *) ((arg1)->syntax); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_flags_set(void * jarg1, unsigned long jarg2) { + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + uint32_t arg2 ; + + arg1 = (switch_chat_application_interface *)jarg1; + arg2 = (uint32_t)jarg2; + if (arg1) (arg1)->flags = arg2; +} + + +SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_chat_application_interface_flags_get(void * jarg1) { + unsigned long jresult ; + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + uint32_t result; + + arg1 = (switch_chat_application_interface *)jarg1; + result = (uint32_t) ((arg1)->flags); + jresult = (unsigned long)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_rwlock_set(void * jarg1, void * jarg2) { + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + switch_thread_rwlock_t *arg2 = (switch_thread_rwlock_t *) 0 ; + + arg1 = (switch_chat_application_interface *)jarg1; + arg2 = (switch_thread_rwlock_t *)jarg2; + if (arg1) (arg1)->rwlock = arg2; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_chat_application_interface_rwlock_get(void * jarg1) { + void * jresult ; + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + switch_thread_rwlock_t *result = 0 ; + + arg1 = (switch_chat_application_interface *)jarg1; + result = (switch_thread_rwlock_t *) ((arg1)->rwlock); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_refs_set(void * jarg1, int jarg2) { + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + int arg2 ; + + arg1 = (switch_chat_application_interface *)jarg1; + arg2 = (int)jarg2; + if (arg1) (arg1)->refs = arg2; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_chat_application_interface_refs_get(void * jarg1) { + int jresult ; + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + int result; + + arg1 = (switch_chat_application_interface *)jarg1; + result = (int) ((arg1)->refs); + jresult = result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_reflock_set(void * jarg1, void * jarg2) { + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + switch_mutex_t *arg2 = (switch_mutex_t *) 0 ; + + arg1 = (switch_chat_application_interface *)jarg1; + arg2 = (switch_mutex_t *)jarg2; + if (arg1) (arg1)->reflock = arg2; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_chat_application_interface_reflock_get(void * jarg1) { + void * jresult ; + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + switch_mutex_t *result = 0 ; + + arg1 = (switch_chat_application_interface *)jarg1; + result = (switch_mutex_t *) ((arg1)->reflock); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_parent_set(void * jarg1, void * jarg2) { + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + switch_loadable_module_interface_t *arg2 = (switch_loadable_module_interface_t *) 0 ; + + arg1 = (switch_chat_application_interface *)jarg1; + arg2 = (switch_loadable_module_interface_t *)jarg2; + if (arg1) (arg1)->parent = arg2; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_chat_application_interface_parent_get(void * jarg1) { + void * jresult ; + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + switch_loadable_module_interface_t *result = 0 ; + + arg1 = (switch_chat_application_interface *)jarg1; + result = (switch_loadable_module_interface_t *) ((arg1)->parent); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_application_interface_next_set(void * jarg1, void * jarg2) { + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + switch_chat_application_interface *arg2 = (switch_chat_application_interface *) 0 ; + + arg1 = (switch_chat_application_interface *)jarg1; + arg2 = (switch_chat_application_interface *)jarg2; + if (arg1) (arg1)->next = arg2; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_chat_application_interface_next_get(void * jarg1) { + void * jresult ; + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + switch_chat_application_interface *result = 0 ; + + arg1 = (switch_chat_application_interface *)jarg1; + result = (switch_chat_application_interface *) ((arg1)->next); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_chat_application_interface() { + void * jresult ; + switch_chat_application_interface *result = 0 ; + + result = (switch_chat_application_interface *)new switch_chat_application_interface(); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_delete_switch_chat_application_interface(void * jarg1) { + switch_chat_application_interface *arg1 = (switch_chat_application_interface *) 0 ; + + arg1 = (switch_chat_application_interface *)jarg1; + delete arg1; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_api_interface_interface_name_set(void * jarg1, char * jarg2) { switch_api_interface *arg1 = (switch_api_interface *) 0 ; char *arg2 = (char *) 0 ; @@ -23802,6 +24342,20 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_hold_music_partner(void } +SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_channel_del_variable_prefix(void * jarg1, char * jarg2) { + unsigned long jresult ; + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + char *arg2 = (char *) 0 ; + uint32_t result; + + arg1 = (switch_channel_t *)jarg1; + arg2 = (char *)jarg2; + result = (uint32_t)switch_channel_del_variable_prefix(arg1,(char const *)arg2); + jresult = (unsigned long)result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_export_variable_var_check(void * jarg1, char * jarg2, char * jarg3, char * jarg4, int jarg5) { int jresult ; switch_channel_t *arg1 = (switch_channel_t *) 0 ; @@ -25747,6 +26301,22 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_event_get_header_idx(void * jarg1, c } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_event_rename_header(void * jarg1, char * jarg2, char * jarg3) { + int jresult ; + switch_event_t *arg1 = (switch_event_t *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + switch_status_t result; + + arg1 = (switch_event_t *)jarg1; + arg2 = (char *)jarg2; + arg3 = (char *)jarg3; + result = (switch_status_t)switch_event_rename_header(arg1,(char const *)arg2,(char const *)arg3); + jresult = result; + return jresult; +} + + SWIGEXPORT char * SWIGSTDCALL CSharp_switch_event_get_body(void * jarg1) { char * jresult ; switch_event_t *arg1 = (switch_event_t *) 0 ; @@ -25855,6 +26425,20 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_event_merge(void * jarg1, void * jarg2 } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_event_dup_reply(void * jarg1, void * jarg2) { + int jresult ; + switch_event_t **arg1 = (switch_event_t **) 0 ; + switch_event_t *arg2 = (switch_event_t *) 0 ; + switch_status_t result; + + arg1 = (switch_event_t **)jarg1; + arg2 = (switch_event_t *)jarg2; + result = (switch_status_t)switch_event_dup_reply(arg1,arg2); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_event_fire_detailed(char * jarg1, char * jarg2, int jarg3, void * jarg4, void * jarg5) { int jresult ; char *arg1 = (char *) 0 ; @@ -26087,6 +26671,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_event_running() { } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_event_set_body(void * jarg1, char * jarg2) { + int jresult ; + switch_event_t *arg1 = (switch_event_t *) 0 ; + char *arg2 = (char *) 0 ; + switch_status_t result; + + arg1 = (switch_event_t *)jarg1; + arg2 = (char *)jarg2; + result = (switch_status_t)switch_event_set_body(arg1,(char const *)arg2); + jresult = result; + return jresult; +} + + SWIGEXPORT char * SWIGSTDCALL CSharp_switch_event_expand_headers(void * jarg1, char * jarg2) { char * jresult ; switch_event_t *arg1 = (switch_event_t *) 0 ; @@ -27225,6 +27823,26 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_collect_digits_count(void * jarg1, } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_play_and_detect_speech(void * jarg1, char * jarg2, char * jarg3, char * jarg4, void * jarg5) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + char *arg4 = (char *) 0 ; + char **arg5 = (char **) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + arg2 = (char *)jarg2; + arg3 = (char *)jarg3; + arg4 = (char *)jarg4; + arg5 = (char **)jarg5; + result = (switch_status_t)switch_ivr_play_and_detect_speech(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4,arg5); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_detect_speech(void * jarg1, char * jarg2, char * jarg3, char * jarg4, char * jarg5, void * jarg6) { int jresult ; switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; @@ -28785,6 +29403,18 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_uuid_exists(char * jarg1) { } +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_ivr_dmachine_get_name(void * jarg1) { + char * jresult ; + switch_ivr_dmachine_t *arg1 = (switch_ivr_dmachine_t *) 0 ; + char *result = 0 ; + + arg1 = (switch_ivr_dmachine_t *)jarg1; + result = (char *)switch_ivr_dmachine_get_name(arg1); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_ivr_dmachine_set_match_callback(void * jarg1, void * jarg2) { switch_ivr_dmachine_t *arg1 = (switch_ivr_dmachine_t *) 0 ; switch_ivr_dmachine_callback_t arg2 = (switch_ivr_dmachine_callback_t) 0 ; @@ -29043,6 +29673,50 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_insert_file(void * jarg1, char * ja } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_create_message_reply(void * jarg1, void * jarg2, char * jarg3) { + int jresult ; + switch_event_t **arg1 = (switch_event_t **) 0 ; + switch_event_t *arg2 = (switch_event_t *) 0 ; + char *arg3 = (char *) 0 ; + switch_status_t result; + + arg1 = (switch_event_t **)jarg1; + arg2 = (switch_event_t *)jarg2; + arg3 = (char *)jarg3; + result = (switch_status_t)switch_ivr_create_message_reply(arg1,arg2,(char const *)arg3); + jresult = result; + return jresult; +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_ivr_check_presence_mapping(char * jarg1, char * jarg2) { + char * jresult ; + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + char *result = 0 ; + + arg1 = (char *)jarg1; + arg2 = (char *)jarg2; + result = (char *)switch_ivr_check_presence_mapping((char const *)arg1,(char const *)arg2); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_kill_uuid(char * jarg1, int jarg2) { + int jresult ; + char *arg1 = (char *) 0 ; + switch_call_cause_t arg2 ; + switch_status_t result; + + arg1 = (char *)jarg1; + arg2 = (switch_call_cause_t)jarg2; + result = (switch_status_t)switch_ivr_kill_uuid((char const *)arg1,arg2); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_SWITCH_RTP_MAX_BUF_LEN_get() { int jresult ; int result; @@ -31536,13 +32210,15 @@ SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_xml_parse_section_string(char } -SWIGEXPORT int SWIGSTDCALL CSharp_switch_xml_std_datetime_check(void * jarg1) { +SWIGEXPORT int SWIGSTDCALL CSharp_switch_xml_std_datetime_check(void * jarg1, void * jarg2) { int jresult ; switch_xml_t arg1 = (switch_xml_t) 0 ; + int *arg2 = (int *) 0 ; int result; arg1 = (switch_xml_t)jarg1; - result = (int)switch_xml_std_datetime_check(arg1); + arg2 = (int *)jarg2; + result = (int)switch_xml_std_datetime_check(arg1,arg2); jresult = result; return jresult; } @@ -33550,6 +34226,29 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_config_next_pair(void * jarg1, void * j } +SWIGEXPORT void SWIGSTDCALL CSharp_setGlobalVariable(char * jarg1, char * jarg2) { + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + + arg1 = (char *)jarg1; + arg2 = (char *)jarg2; + setGlobalVariable(arg1,arg2); +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_getGlobalVariable(char * jarg1) { + char * jresult ; + char *arg1 = (char *) 0 ; + char *result = 0 ; + + arg1 = (char *)jarg1; + result = (char *)getGlobalVariable(arg1); + jresult = SWIG_csharp_string_callback((const char *)result); + free(result); + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_consoleLog(char * jarg1, char * jarg2) { char *arg1 = (char *) 0 ; char *arg2 = (char *) 0 ; @@ -34070,6 +34769,36 @@ SWIGEXPORT void SWIGSTDCALL CSharp_delete_Event(void * jarg1) { } +SWIGEXPORT int SWIGSTDCALL CSharp_Event_chat_execute(void * jarg1, char * jarg2, char * jarg3) { + int jresult ; + Event *arg1 = (Event *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) NULL ; + int result; + + arg1 = (Event *)jarg1; + arg2 = (char *)jarg2; + arg3 = (char *)jarg3; + result = (int)(arg1)->chat_execute((char const *)arg2,(char const *)arg3); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_Event_chat_send(void * jarg1, char * jarg2) { + int jresult ; + Event *arg1 = (Event *) 0 ; + char *arg2 = (char *) NULL ; + int result; + + arg1 = (Event *)jarg1; + arg2 = (char *)jarg2; + result = (int)(arg1)->chat_send((char const *)arg2); + jresult = result; + return jresult; +} + + SWIGEXPORT char * SWIGSTDCALL CSharp_Event_Serialize(void * jarg1, char * jarg2) { char * jresult ; Event *arg1 = (Event *) 0 ; @@ -34412,15 +35141,17 @@ SWIGEXPORT int SWIGSTDCALL CSharp_EventConsumer_bind(void * jarg1, char * jarg2, } -SWIGEXPORT void * SWIGSTDCALL CSharp_EventConsumer_pop(void * jarg1, int jarg2) { +SWIGEXPORT void * SWIGSTDCALL CSharp_EventConsumer_pop(void * jarg1, int jarg2, int jarg3) { void * jresult ; EventConsumer *arg1 = (EventConsumer *) 0 ; int arg2 = (int) 0 ; + int arg3 = (int) 0 ; Event *result = 0 ; arg1 = (EventConsumer *)jarg1; arg2 = (int)jarg2; - result = (Event *)(arg1)->pop(arg2); + arg3 = (int)jarg3; + result = (Event *)(arg1)->pop(arg2,arg3); jresult = (void *)result; return jresult; } diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx index 8bacc37b85..a57e78574b 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx @@ -259,7 +259,6 @@ SWIGEXPORT void SWIGSTDCALL SWIGRegisterExceptionArgumentCallbacks_freeswitch( /* Callback for returning strings to C# without leaking memory */ #ifndef _MANAGED -#include #include #include #include @@ -1136,6 +1135,28 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE } +SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_TRANSFER_HISTORY_VARIABLE_get() { + char * jresult ; + char *result = 0 ; + + result = (char *) "transfer_history"; + + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_TRANSFER_SOURCE_VARIABLE_get() { + char * jresult ; + char *result = 0 ; + + result = (char *) "transfer_source"; + + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE_get() { char * jresult ; char *result = 0 ; @@ -4047,6 +4068,35 @@ SWIGEXPORT unsigned short SWIGSTDCALL CSharp_switch_t38_options_t_local_port_get } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_t38_options_t_sdp_o_line_set(void * jarg1, char * jarg2) { + switch_t38_options_t *arg1 = (switch_t38_options_t *) 0 ; + char *arg2 = (char *) 0 ; + + arg1 = (switch_t38_options_t *)jarg1; + arg2 = (char *)jarg2; + { + if (arg2) { + arg1->sdp_o_line = (char const *) (new char[strlen((const char *)arg2)+1]); + strcpy((char *)arg1->sdp_o_line, (const char *)arg2); + } else { + arg1->sdp_o_line = 0; + } + } +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_t38_options_t_sdp_o_line_get(void * jarg1) { + char * jresult ; + switch_t38_options_t *arg1 = (switch_t38_options_t *) 0 ; + char *result = 0 ; + + arg1 = (switch_t38_options_t *)jarg1; + result = (char *) ((arg1)->sdp_o_line); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_t38_options_t() { void * jresult ; switch_t38_options_t *result = 0 ; @@ -7123,30 +7173,6 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_add_state_handler(void * jarg1) { } -SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_curl_count(void * jarg1) { - int jresult ; - int *arg1 = (int *) 0 ; - int result; - - arg1 = (int *)jarg1; - result = (int)switch_core_curl_count(arg1); - jresult = result; - return jresult; -} - - -SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_ssl_count(void * jarg1) { - int jresult ; - int *arg1 = (int *) 0 ; - int result; - - arg1 = (int *)jarg1; - result = (int)switch_core_ssl_count(arg1); - jresult = result; - return jresult; -} - - SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_remove_state_handler(void * jarg1) { switch_state_handler_table_t *arg1 = (switch_state_handler_table_t *) 0 ; @@ -7195,6 +7221,16 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_perform_new_memory_pool(void * jar } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_sync_clock() { + int jresult ; + int result; + + result = (int)switch_core_session_sync_clock(); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_perform_destroy_memory_pool(void * jarg1, char * jarg2, char * jarg3, int jarg4) { int jresult ; switch_memory_pool_t **arg1 = (switch_memory_pool_t **) 0 ; @@ -9970,6 +10006,26 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_ready() { } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_ready_inbound() { + int jresult ; + switch_bool_t result; + + result = (switch_bool_t)switch_core_ready_inbound(); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_ready_outbound() { + int jresult ; + switch_bool_t result; + + result = (switch_bool_t)switch_core_ready_outbound(); + jresult = result; + return jresult; +} + + SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_core_flags() { unsigned long jresult ; switch_core_flag_t result; @@ -12909,6 +12965,22 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_is_number(char * jarg1) { } +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_find_parameter(char * jarg1, char * jarg2, void * jarg3) { + char * jresult ; + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + switch_memory_pool_t *arg3 = (switch_memory_pool_t *) 0 ; + char *result = 0 ; + + arg1 = (char *)jarg1; + arg2 = (char *)jarg2; + arg3 = (switch_memory_pool_t *)jarg3; + result = (char *)switch_find_parameter((char const *)arg1,(char const *)arg2,arg3); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_true(char * jarg1) { int jresult ; char *arg1 = (char *) 0 ; @@ -13203,6 +13275,20 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_clean_name_string(char * jarg1) { } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_safe_atoi(char * jarg1, int jarg2) { + int jresult ; + char *arg1 = (char *) 0 ; + int arg2 ; + int result; + + arg1 = (char *)jarg1; + arg2 = (int)jarg2; + result = (int)switch_safe_atoi((char const *)arg1,arg2); + jresult = result; + return jresult; +} + + SWIGEXPORT char * SWIGSTDCALL CSharp_switch_safe_strdup(char * jarg1) { char * jresult ; char *arg1 = (char *) 0 ; @@ -13883,6 +13969,38 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_split_user_domain(char * jarg1, void * } +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_uuid_str(char * jarg1, void * jarg2) { + char * jresult ; + char *arg1 = (char *) 0 ; + switch_size_t arg2 ; + char *result = 0 ; + switch_size_t *argp2 ; + + arg1 = (char *)jarg1; + argp2 = (switch_size_t *)jarg2; + if (!argp2) { + SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null switch_size_t", 0); + return 0; + } + arg2 = *argp2; + result = (char *)switch_uuid_str(arg1,arg2); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_format_number(char * jarg1) { + char * jresult ; + char *arg1 = (char *) 0 ; + char *result = 0 ; + + arg1 = (char *)jarg1; + result = (char *)switch_format_number((char const *)arg1); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_profile_node_t_var_set(void * jarg1, char * jarg2) { profile_node_t *arg1 = (profile_node_t *) 0 ; char *arg2 = (char *) 0 ; @@ -14889,6 +15007,96 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_switch_caller_profile_soft_get(void * jarg1 } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_caller_profile_uuid_str_set(void * jarg1, char * jarg2) { + switch_caller_profile *arg1 = (switch_caller_profile *) 0 ; + char *arg2 = (char *) 0 ; + + arg1 = (switch_caller_profile *)jarg1; + arg2 = (char *)jarg2; + { + if (arg1->uuid_str) delete [] arg1->uuid_str; + if (arg2) { + arg1->uuid_str = (char *) (new char[strlen((const char *)arg2)+1]); + strcpy((char *)arg1->uuid_str, (const char *)arg2); + } else { + arg1->uuid_str = 0; + } + } +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_caller_profile_uuid_str_get(void * jarg1) { + char * jresult ; + switch_caller_profile *arg1 = (switch_caller_profile *) 0 ; + char *result = 0 ; + + arg1 = (switch_caller_profile *)jarg1; + result = (char *) ((arg1)->uuid_str); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_caller_profile_clone_of_set(void * jarg1, char * jarg2) { + switch_caller_profile *arg1 = (switch_caller_profile *) 0 ; + char *arg2 = (char *) 0 ; + + arg1 = (switch_caller_profile *)jarg1; + arg2 = (char *)jarg2; + { + if (arg1->clone_of) delete [] arg1->clone_of; + if (arg2) { + arg1->clone_of = (char *) (new char[strlen((const char *)arg2)+1]); + strcpy((char *)arg1->clone_of, (const char *)arg2); + } else { + arg1->clone_of = 0; + } + } +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_caller_profile_clone_of_get(void * jarg1) { + char * jresult ; + switch_caller_profile *arg1 = (switch_caller_profile *) 0 ; + char *result = 0 ; + + arg1 = (switch_caller_profile *)jarg1; + result = (char *) ((arg1)->clone_of); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_caller_profile_transfer_source_set(void * jarg1, char * jarg2) { + switch_caller_profile *arg1 = (switch_caller_profile *) 0 ; + char *arg2 = (char *) 0 ; + + arg1 = (switch_caller_profile *)jarg1; + arg2 = (char *)jarg2; + { + if (arg1->transfer_source) delete [] arg1->transfer_source; + if (arg2) { + arg1->transfer_source = (char *) (new char[strlen((const char *)arg2)+1]); + strcpy((char *)arg1->transfer_source, (const char *)arg2); + } else { + arg1->transfer_source = 0; + } + } +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_caller_profile_transfer_source_get(void * jarg1) { + char * jresult ; + switch_caller_profile *arg1 = (switch_caller_profile *) 0 ; + char *result = 0 ; + + arg1 = (switch_caller_profile *)jarg1; + result = (char *) ((arg1)->transfer_source); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_caller_profile() { void * jresult ; switch_caller_profile *result = 0 ; @@ -24856,6 +25064,20 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_hold_music_partner(void } +SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_channel_del_variable_prefix(void * jarg1, char * jarg2) { + unsigned long jresult ; + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + char *arg2 = (char *) 0 ; + uint32_t result; + + arg1 = (switch_channel_t *)jarg1; + arg2 = (char *)jarg2; + result = (uint32_t)switch_channel_del_variable_prefix(arg1,(char const *)arg2); + jresult = (unsigned long)result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_export_variable_var_check(void * jarg1, char * jarg2, char * jarg3, char * jarg4, int jarg5) { int jresult ; switch_channel_t *arg1 = (switch_channel_t *) 0 ; @@ -25201,6 +25423,16 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_channel_set_state_flag(void * jarg1, i } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_channel_clear_state_flag(void * jarg1, int jarg2) { + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + switch_channel_flag_t arg2 ; + + arg1 = (switch_channel_t *)jarg1; + arg2 = (switch_channel_flag_t)jarg2; + switch_channel_clear_state_flag(arg1,arg2); +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_channel_clear_flag(void * jarg1, int jarg2) { switch_channel_t *arg1 = (switch_channel_t *) 0 ; switch_channel_flag_t arg2 ; @@ -28362,6 +28594,26 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_collect_digits_count(void * jarg1, } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_play_and_detect_speech(void * jarg1, char * jarg2, char * jarg3, char * jarg4, void * jarg5) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + char *arg4 = (char *) 0 ; + char **arg5 = (char **) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + arg2 = (char *)jarg2; + arg3 = (char *)jarg3; + arg4 = (char *)jarg4; + arg5 = (char **)jarg5; + result = (switch_status_t)switch_ivr_play_and_detect_speech(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4,arg5); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_detect_speech(void * jarg1, char * jarg2, char * jarg3, char * jarg4, char * jarg5, void * jarg6) { int jresult ; switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; @@ -29922,6 +30174,18 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_uuid_exists(char * jarg1) { } +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_ivr_dmachine_get_name(void * jarg1) { + char * jresult ; + switch_ivr_dmachine_t *arg1 = (switch_ivr_dmachine_t *) 0 ; + char *result = 0 ; + + arg1 = (switch_ivr_dmachine_t *)jarg1; + result = (char *)switch_ivr_dmachine_get_name(arg1); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_ivr_dmachine_set_match_callback(void * jarg1, void * jarg2) { switch_ivr_dmachine_t *arg1 = (switch_ivr_dmachine_t *) 0 ; switch_ivr_dmachine_callback_t arg2 = (switch_ivr_dmachine_callback_t) 0 ; @@ -30196,6 +30460,34 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_create_message_reply(void * jarg1, } +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_ivr_check_presence_mapping(char * jarg1, char * jarg2) { + char * jresult ; + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + char *result = 0 ; + + arg1 = (char *)jarg1; + arg2 = (char *)jarg2; + result = (char *)switch_ivr_check_presence_mapping((char const *)arg1,(char const *)arg2); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_kill_uuid(char * jarg1, int jarg2) { + int jresult ; + char *arg1 = (char *) 0 ; + switch_call_cause_t arg2 ; + switch_status_t result; + + arg1 = (char *)jarg1; + arg2 = (switch_call_cause_t)jarg2; + result = (switch_status_t)switch_ivr_kill_uuid((char const *)arg1,arg2); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_SWITCH_RTP_MAX_BUF_LEN_get() { int jresult ; int result; @@ -32709,13 +33001,15 @@ SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_xml_parse_section_string(char } -SWIGEXPORT int SWIGSTDCALL CSharp_switch_xml_std_datetime_check(void * jarg1) { +SWIGEXPORT int SWIGSTDCALL CSharp_switch_xml_std_datetime_check(void * jarg1, void * jarg2) { int jresult ; switch_xml_t arg1 = (switch_xml_t) 0 ; + int *arg2 = (int *) 0 ; int result; arg1 = (switch_xml_t)jarg1; - result = (int)switch_xml_std_datetime_check(arg1); + arg2 = (int *)jarg2; + result = (int)switch_xml_std_datetime_check(arg1,arg2); jresult = result; return jresult; } @@ -34772,6 +35066,29 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_config_next_pair(void * jarg1, void * j } +SWIGEXPORT void SWIGSTDCALL CSharp_setGlobalVariable(char * jarg1, char * jarg2) { + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + + arg1 = (char *)jarg1; + arg2 = (char *)jarg2; + setGlobalVariable(arg1,arg2); +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_getGlobalVariable(char * jarg1) { + char * jresult ; + char *arg1 = (char *) 0 ; + char *result = 0 ; + + arg1 = (char *)jarg1; + result = (char *)getGlobalVariable(arg1); + jresult = SWIG_csharp_string_callback((const char *)result); + free(result); + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_consoleLog(char * jarg1, char * jarg2) { char *arg1 = (char *) 0 ; char *arg2 = (char *) 0 ; @@ -35681,15 +35998,17 @@ SWIGEXPORT int SWIGSTDCALL CSharp_EventConsumer_bind(void * jarg1, char * jarg2, } -SWIGEXPORT void * SWIGSTDCALL CSharp_EventConsumer_pop(void * jarg1, int jarg2) { +SWIGEXPORT void * SWIGSTDCALL CSharp_EventConsumer_pop(void * jarg1, int jarg2, int jarg3) { void * jresult ; EventConsumer *arg1 = (EventConsumer *) 0 ; int arg2 = (int) 0 ; + int arg3 = (int) 0 ; Event *result = 0 ; arg1 = (EventConsumer *)jarg1; arg2 = (int)jarg2; - result = (Event *)(arg1)->pop(arg2); + arg3 = (int)jarg3; + result = (Event *)(arg1)->pop(arg2,arg3); jresult = (void *)result; return jresult; } diff --git a/src/mod/languages/mod_managed/managed/Loader.cs b/src/mod/languages/mod_managed/managed/Loader.cs index 8912a4e949..19ab3a52db 100644 --- a/src/mod/languages/mod_managed/managed/Loader.cs +++ b/src/mod/languages/mod_managed/managed/Loader.cs @@ -47,13 +47,15 @@ namespace FreeSWITCH { [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate bool ExecuteBackgroundDelegate(string cmd); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate bool RunDelegate(string cmd, IntPtr session); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate bool ReloadDelegate(string cmd); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate bool ListDelegate(string cmd); static readonly ExecuteDelegate _execute = Execute; static readonly ExecuteBackgroundDelegate _executeBackground = ExecuteBackground; static readonly RunDelegate _run = Run; static readonly ReloadDelegate _reload = Reload; - //SWITCH_MOD_DECLARE_NONSTD(void) InitManagedDelegates(runFunction run, executeFunction execute, executeBackgroundFunction executeBackground, reloadFunction reload) + static readonly ListDelegate _list = List; + [DllImport("mod_managed", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] - static extern void InitManagedDelegates(RunDelegate run, ExecuteDelegate execute, ExecuteBackgroundDelegate executeBackground, ReloadDelegate reload); + static extern void InitManagedDelegates(RunDelegate run, ExecuteDelegate execute, ExecuteBackgroundDelegate executeBackground, ReloadDelegate reload, ListDelegate list); static readonly object loaderLock = new object(); @@ -83,7 +85,7 @@ namespace FreeSWITCH { return File.Exists(path) ? Assembly.LoadFile(path) : null; }; - InitManagedDelegates(_run, _execute, _executeBackground, _reload); + InitManagedDelegates(_run, _execute, _executeBackground, _reload, _list); configureWatcher(); @@ -405,7 +407,24 @@ namespace FreeSWITCH { return false; } } + + public static bool List(string command) { + try { + Log.WriteLine(LogLevel.Info, "Available APIs:"); + getApiExecs().Values.ForEach(x => { + Log.WriteLine(LogLevel.Info, "{0}: {1}", x.Name, String.Join(",", x.Aliases.ToArray())); + }); + Log.WriteLine(LogLevel.Info, "Available Apps:"); + getAppExecs().Values.ForEach(x => { + Log.WriteLine(LogLevel.Info, "{0}: {1}", x.Name, String.Join(",", x.Aliases.ToArray())); + }); + return true; + } catch (Exception ex) { + Log.WriteLine(LogLevel.Error, "Exception listing managed modules: {0}", ex.ToString()); + return false; + } + } } } - \ No newline at end of file + diff --git a/src/mod/languages/mod_managed/managed/ManagedSession.cs b/src/mod/languages/mod_managed/managed/ManagedSession.cs index 26f04b9935..07832ae102 100644 --- a/src/mod/languages/mod_managed/managed/ManagedSession.cs +++ b/src/mod/languages/mod_managed/managed/ManagedSession.cs @@ -50,7 +50,7 @@ namespace FreeSWITCH.Native public partial class ManagedSession { // SWITCH_DECLARE(void) InitManagedSession(ManagedSession *session, MonoObject *dtmfDelegate, MonoObject *hangupDelegate) - [DllImport("mod_managed.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] + [DllImport("mod_managed", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] static extern void InitManagedSession(IntPtr sessionPtr, DtmfCallback dtmfDelegate, CdeclAction hangupDelegate); /// Initializes the native ManagedSession. Called after Originate completes successfully . diff --git a/src/mod/languages/mod_managed/managed/PluginManager.cs b/src/mod/languages/mod_managed/managed/PluginManager.cs index adf78f26cc..f9bcf7f5b5 100644 --- a/src/mod/languages/mod_managed/managed/PluginManager.cs +++ b/src/mod/languages/mod_managed/managed/PluginManager.cs @@ -111,6 +111,9 @@ namespace FreeSWITCH { return false; } } + } catch (Exception ex) { + Log.WriteLine(LogLevel.Error, "Error in plugin execute: " + ex.ToString()); + return false; } finally { DecreaseUse(); } @@ -280,7 +283,7 @@ namespace FreeSWITCH { protected override bool LoadInternal(string fileName) { Assembly asm; try { - asm = Assembly.LoadFrom(fileName); + asm = Assembly.Load(System.IO.File.ReadAllBytes(fileName)); } catch (Exception ex) { Log.WriteLine(LogLevel.Info, "Couldn't load {0}: {1}", fileName, ex.Message); return false; diff --git a/src/mod/languages/mod_managed/managed/swig.2010.cs b/src/mod/languages/mod_managed/managed/swig.2010.cs index e8f921b6f4..36729f7847 100644 --- a/src/mod/languages/mod_managed/managed/swig.2010.cs +++ b/src/mod/languages/mod_managed/managed/swig.2010.cs @@ -615,6 +615,16 @@ public partial class Event : IDisposable { public Event(switch_event wrap_me, int free_me) : this(freeswitchPINVOKE.new_Event__SWIG_1(switch_event.getCPtr(wrap_me), free_me), true) { } + public int chat_execute(string app, string data) { + int ret = freeswitchPINVOKE.Event_chat_execute(swigCPtr, app, data); + return ret; + } + + public int chat_send(string dest_proto) { + int ret = freeswitchPINVOKE.Event_chat_send(swigCPtr, dest_proto); + return ret; + } + public string Serialize(string format) { string ret = freeswitchPINVOKE.Event_Serialize(swigCPtr, format); return ret; @@ -786,8 +796,8 @@ public class EventConsumer : IDisposable { return ret; } - public Event pop(int block) { - IntPtr cPtr = freeswitchPINVOKE.EventConsumer_pop(swigCPtr, block); + public Event pop(int block, int timeout) { + IntPtr cPtr = freeswitchPINVOKE.EventConsumer_pop(swigCPtr, block, timeout); Event ret = (cPtr == IntPtr.Zero) ? null : new Event(cPtr, true); return ret; } @@ -967,6 +977,10 @@ public class freeswitch { freeswitchPINVOKE.switch_regex_set_var_callback(var, val, SWIGTYPE_p_void.getCPtr(user_data)); } + public static void switch_regex_set_event_header_callback(string var, string val, SWIGTYPE_p_void user_data) { + freeswitchPINVOKE.switch_regex_set_event_header_callback(var, val, SWIGTYPE_p_void.getCPtr(user_data)); + } + public static void switch_core_session_sched_heartbeat(SWIGTYPE_p_switch_core_session session, uint seconds) { freeswitchPINVOKE.switch_core_session_sched_heartbeat(SWIGTYPE_p_switch_core_session.getCPtr(session), seconds); } @@ -1179,16 +1193,6 @@ public class freeswitch { return ret; } - public static int switch_core_curl_count(SWIGTYPE_p_int val) { - int ret = freeswitchPINVOKE.switch_core_curl_count(SWIGTYPE_p_int.getCPtr(val)); - return ret; - } - - public static int switch_core_ssl_count(SWIGTYPE_p_int val) { - int ret = freeswitchPINVOKE.switch_core_ssl_count(SWIGTYPE_p_int.getCPtr(val)); - return ret; - } - public static void switch_core_remove_state_handler(switch_state_handler_table state_handler) { freeswitchPINVOKE.switch_core_remove_state_handler(switch_state_handler_table.getCPtr(state_handler)); } @@ -1208,6 +1212,11 @@ public class freeswitch { return ret; } + public static int switch_core_session_sync_clock() { + int ret = freeswitchPINVOKE.switch_core_session_sync_clock(); + return ret; + } + public static switch_status_t switch_core_perform_destroy_memory_pool(SWIGTYPE_p_p_apr_pool_t pool, string file, string func, int line) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_perform_destroy_memory_pool(SWIGTYPE_p_p_apr_pool_t.getCPtr(pool), file, func, line); return ret; @@ -1788,8 +1797,8 @@ public class freeswitch { return ret; } - public static SWIGTYPE_p_HashElem switch_hash_first(string depricate_me, SWIGTYPE_p_switch_hash hash) { - IntPtr cPtr = freeswitchPINVOKE.switch_hash_first(depricate_me, SWIGTYPE_p_switch_hash.getCPtr(hash)); + public static SWIGTYPE_p_HashElem switch_hash_first(string deprecate_me, SWIGTYPE_p_switch_hash hash) { + IntPtr cPtr = freeswitchPINVOKE.switch_hash_first(deprecate_me, SWIGTYPE_p_switch_hash.getCPtr(hash)); SWIGTYPE_p_HashElem ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_HashElem(cPtr, false); return ret; } @@ -2434,6 +2443,11 @@ public class freeswitch { return ret; } + public static switch_status_t switch_core_chat_deliver(string dest_proto, SWIGTYPE_p_p_switch_event message_event) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_chat_deliver(dest_proto, SWIGTYPE_p_p_switch_event.getCPtr(message_event)); + return ret; + } + public static switch_status_t switch_ivr_preprocess_session(SWIGTYPE_p_switch_core_session session, string cmds) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_preprocess_session(SWIGTYPE_p_switch_core_session.getCPtr(session), cmds); return ret; @@ -2631,6 +2645,17 @@ public class freeswitch { return ret; } + public static switch_chat_application_interface switch_loadable_module_get_chat_application_interface(string name) { + IntPtr cPtr = freeswitchPINVOKE.switch_loadable_module_get_chat_application_interface(name); + switch_chat_application_interface ret = (cPtr == IntPtr.Zero) ? null : new switch_chat_application_interface(cPtr, false); + return ret; + } + + public static switch_status_t switch_core_execute_chat_app(switch_event message, string app, string data) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_execute_chat_app(switch_event.getCPtr(message), app, data); + return ret; + } + public static switch_api_interface switch_loadable_module_get_api_interface(string name) { IntPtr cPtr = freeswitchPINVOKE.switch_loadable_module_get_api_interface(name); switch_api_interface ret = (cPtr == IntPtr.Zero) ? null : new switch_api_interface(cPtr, false); @@ -2961,6 +2986,11 @@ public class freeswitch { return ret; } + public static string switch_find_parameter(string str, string param, SWIGTYPE_p_apr_pool_t pool) { + string ret = freeswitchPINVOKE.switch_find_parameter(str, param, SWIGTYPE_p_apr_pool_t.getCPtr(pool)); + return ret; + } + public static int switch_true(string expr) { int ret = freeswitchPINVOKE.switch_true(expr); return ret; @@ -3059,6 +3089,11 @@ public class freeswitch { return ret; } + public static int switch_safe_atoi(string nptr, int dft) { + int ret = freeswitchPINVOKE.switch_safe_atoi(nptr, dft); + return ret; + } + public static string switch_safe_strdup(string it) { string ret = freeswitchPINVOKE.switch_safe_strdup(it); return ret; @@ -3281,6 +3316,17 @@ public class freeswitch { return ret; } + public static string switch_uuid_str(string buf, SWIGTYPE_p_switch_size_t len) { + string ret = freeswitchPINVOKE.switch_uuid_str(buf, SWIGTYPE_p_switch_size_t.getCPtr(len)); + if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + public static string switch_format_number(string num) { + string ret = freeswitchPINVOKE.switch_format_number(num); + return ret; + } + public static switch_caller_extension switch_caller_extension_new(SWIGTYPE_p_switch_core_session session, string extension_name, string extension_number) { IntPtr cPtr = freeswitchPINVOKE.switch_caller_extension_new(SWIGTYPE_p_switch_core_session.getCPtr(session), extension_name, extension_number); switch_caller_extension ret = (cPtr == IntPtr.Zero) ? null : new switch_caller_extension(cPtr, false); @@ -3519,6 +3565,11 @@ public class freeswitch { return ret; } + public static uint switch_channel_del_variable_prefix(SWIGTYPE_p_switch_channel channel, string prefix) { + uint ret = freeswitchPINVOKE.switch_channel_del_variable_prefix(SWIGTYPE_p_switch_channel.getCPtr(channel), prefix); + return ret; + } + public static switch_status_t switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel channel, string varname, string val, string export_varname, switch_bool_t var_check) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel.getCPtr(channel), varname, val, export_varname, (int)var_check); return ret; @@ -4037,6 +4088,11 @@ public class freeswitch { return ret; } + public static switch_status_t switch_event_rename_header(switch_event arg0, string header_name, string new_header_name) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_event_rename_header(switch_event.getCPtr(arg0), header_name, new_header_name); + return ret; + } + public static string switch_event_get_body(switch_event arg0) { string ret = freeswitchPINVOKE.switch_event_get_body(switch_event.getCPtr(arg0)); return ret; @@ -4075,6 +4131,11 @@ public class freeswitch { freeswitchPINVOKE.switch_event_merge(switch_event.getCPtr(arg0), switch_event.getCPtr(tomerge)); } + public static switch_status_t switch_event_dup_reply(SWIGTYPE_p_p_switch_event arg0, switch_event todup) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_event_dup_reply(SWIGTYPE_p_p_switch_event.getCPtr(arg0), switch_event.getCPtr(todup)); + return ret; + } + public static switch_status_t switch_event_fire_detailed(string file, string func, int line, SWIGTYPE_p_p_switch_event arg3, SWIGTYPE_p_void user_data) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_event_fire_detailed(file, func, line, SWIGTYPE_p_p_switch_event.getCPtr(arg3), SWIGTYPE_p_void.getCPtr(user_data)); return ret; @@ -4149,6 +4210,11 @@ public class freeswitch { return ret; } + public static switch_status_t switch_event_set_body(switch_event arg0, string body) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_event_set_body(switch_event.getCPtr(arg0), body); + return ret; + } + public static string switch_event_expand_headers(switch_event arg0, string arg1) { string ret = freeswitchPINVOKE.switch_event_expand_headers(switch_event.getCPtr(arg0), arg1); return ret; @@ -4310,6 +4376,11 @@ public class freeswitch { return ret; } + public static switch_status_t switch_ivr_play_and_detect_speech(SWIGTYPE_p_switch_core_session session, string file, string mod_name, string grammar, ref string result) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_play_and_detect_speech(SWIGTYPE_p_switch_core_session.getCPtr(session), file, mod_name, grammar, ref result); + return ret; + } + public static switch_status_t switch_ivr_detect_speech(SWIGTYPE_p_switch_core_session session, string mod_name, string grammar, string name, string dest, switch_asr_handle ah) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_detect_speech(SWIGTYPE_p_switch_core_session.getCPtr(session), mod_name, grammar, name, dest, switch_asr_handle.getCPtr(ah)); return ret; @@ -4774,6 +4845,11 @@ public class freeswitch { return ret; } + public static string switch_ivr_dmachine_get_name(SWIGTYPE_p_switch_ivr_dmachine dmachine) { + string ret = freeswitchPINVOKE.switch_ivr_dmachine_get_name(SWIGTYPE_p_switch_ivr_dmachine.getCPtr(dmachine)); + return ret; + } + public static void switch_ivr_dmachine_set_match_callback(SWIGTYPE_p_switch_ivr_dmachine dmachine, SWIGTYPE_p_f_p_switch_ivr_dmachine_match__switch_status_t match_callback) { freeswitchPINVOKE.switch_ivr_dmachine_set_match_callback(SWIGTYPE_p_switch_ivr_dmachine.getCPtr(dmachine), SWIGTYPE_p_f_p_switch_ivr_dmachine_match__switch_status_t.getCPtr(match_callback)); } @@ -4861,6 +4937,21 @@ public class freeswitch { return ret; } + public static switch_status_t switch_ivr_create_message_reply(SWIGTYPE_p_p_switch_event reply, switch_event message, string new_proto) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_create_message_reply(SWIGTYPE_p_p_switch_event.getCPtr(reply), switch_event.getCPtr(message), new_proto); + return ret; + } + + public static string switch_ivr_check_presence_mapping(string exten_name, string domain_name) { + string ret = freeswitchPINVOKE.switch_ivr_check_presence_mapping(exten_name, domain_name); + return ret; + } + + public static switch_status_t switch_ivr_kill_uuid(string uuid, switch_call_cause_t cause) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_kill_uuid(uuid, (int)cause); + return ret; + } + public static switch_status_t switch_rtp_add_crypto_key(SWIGTYPE_p_switch_rtp rtp_session, switch_rtp_crypto_direction_t direction, uint index, switch_rtp_crypto_key_type_t type, SWIGTYPE_p_unsigned_char key, SWIGTYPE_p_switch_size_t keylen) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_add_crypto_key(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), (int)direction, index, (int)type, SWIGTYPE_p_unsigned_char.getCPtr(key), SWIGTYPE_p_switch_size_t.getCPtr(keylen)); if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); @@ -5467,8 +5558,8 @@ public class freeswitch { return ret; } - public static int switch_xml_std_datetime_check(switch_xml xcond) { - int ret = freeswitchPINVOKE.switch_xml_std_datetime_check(switch_xml.getCPtr(xcond)); + public static int switch_xml_std_datetime_check(switch_xml xcond, SWIGTYPE_p_int offset) { + int ret = freeswitchPINVOKE.switch_xml_std_datetime_check(switch_xml.getCPtr(xcond), SWIGTYPE_p_int.getCPtr(offset)); return ret; } @@ -5645,6 +5736,15 @@ public class freeswitch { return ret; } + public static void setGlobalVariable(string var_name, string var_val) { + freeswitchPINVOKE.setGlobalVariable(var_name, var_val); + } + + public static string getGlobalVariable(string var_name) { + string ret = freeswitchPINVOKE.getGlobalVariable(var_name); + return ret; + } + public static void consoleLog(string level_str, string msg) { freeswitchPINVOKE.consoleLog(level_str, msg); } @@ -5761,6 +5861,7 @@ public class freeswitch { public static readonly string SWITCH_READ_RESULT_VARIABLE = freeswitchPINVOKE.SWITCH_READ_RESULT_VARIABLE_get(); public static readonly string SWITCH_COPY_XML_CDR_VARIABLE = freeswitchPINVOKE.SWITCH_COPY_XML_CDR_VARIABLE_get(); public static readonly string SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE = freeswitchPINVOKE.SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE_get(); + public static readonly string SWITCH_TRANSFER_HISTORY_VARIABLE = freeswitchPINVOKE.SWITCH_TRANSFER_HISTORY_VARIABLE_get(); public static readonly string SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE = freeswitchPINVOKE.SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE_get(); public static readonly string SWITCH_CHANNEL_EXECUTE_ON_PRE_ANSWER_VARIABLE = freeswitchPINVOKE.SWITCH_CHANNEL_EXECUTE_ON_PRE_ANSWER_VARIABLE_get(); public static readonly string SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE = freeswitchPINVOKE.SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE_get(); @@ -6310,6 +6411,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE_get")] public static extern string SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE_get(); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_TRANSFER_HISTORY_VARIABLE_get")] + public static extern string SWITCH_TRANSFER_HISTORY_VARIABLE_get(); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE_get")] public static extern string SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE_get(); @@ -7042,6 +7146,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_t38_options_t_local_port_get")] public static extern ushort switch_t38_options_t_local_port_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_t38_options_t_sdp_o_line_set")] + public static extern void switch_t38_options_t_sdp_o_line_set(HandleRef jarg1, string jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_t38_options_t_sdp_o_line_get")] + public static extern string switch_t38_options_t_sdp_o_line_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_new_switch_t38_options_t")] public static extern IntPtr new_switch_t38_options_t(); @@ -7423,6 +7533,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_regex_set_var_callback")] public static extern void switch_regex_set_var_callback(string jarg1, string jarg2, HandleRef jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_regex_set_event_header_callback")] + public static extern void switch_regex_set_event_header_callback(string jarg1, string jarg2, HandleRef jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_MAX_CORE_THREAD_SESSION_OBJS_get")] public static extern int SWITCH_MAX_CORE_THREAD_SESSION_OBJS_get(); @@ -7792,12 +7905,6 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_add_state_handler")] public static extern int switch_core_add_state_handler(HandleRef jarg1); - [DllImport("mod_managed", EntryPoint="CSharp_switch_core_curl_count")] - public static extern int switch_core_curl_count(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_core_ssl_count")] - public static extern int switch_core_ssl_count(HandleRef jarg1); - [DllImport("mod_managed", EntryPoint="CSharp_switch_core_remove_state_handler")] public static extern void switch_core_remove_state_handler(HandleRef jarg1); @@ -7810,6 +7917,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_perform_new_memory_pool")] public static extern int switch_core_perform_new_memory_pool(HandleRef jarg1, string jarg2, string jarg3, int jarg4); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_sync_clock")] + public static extern int switch_core_session_sync_clock(); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_perform_destroy_memory_pool")] public static extern int switch_core_perform_destroy_memory_pool(HandleRef jarg1, string jarg2, string jarg3, int jarg4); @@ -8554,6 +8664,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_chat_send")] public static extern int switch_core_chat_send(string jarg1, HandleRef jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_chat_deliver")] + public static extern int switch_core_chat_deliver(string jarg1, HandleRef jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_preprocess_session")] public static extern int switch_ivr_preprocess_session(HandleRef jarg1, string jarg2); @@ -8755,6 +8868,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_loadable_module_interface_application_interface_get")] public static extern IntPtr switch_loadable_module_interface_application_interface_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_loadable_module_interface_chat_application_interface_set")] + public static extern void switch_loadable_module_interface_chat_application_interface_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_loadable_module_interface_chat_application_interface_get")] + public static extern IntPtr switch_loadable_module_interface_chat_application_interface_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_loadable_module_interface_api_interface_set")] public static extern void switch_loadable_module_interface_api_interface_set(HandleRef jarg1, HandleRef jarg2); @@ -8863,6 +8982,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_loadable_module_get_application_interface")] public static extern IntPtr switch_loadable_module_get_application_interface(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_loadable_module_get_chat_application_interface")] + public static extern IntPtr switch_loadable_module_get_chat_application_interface(string jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_execute_chat_app")] + public static extern int switch_core_execute_chat_app(HandleRef jarg1, string jarg2, string jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_loadable_module_get_api_interface")] public static extern IntPtr switch_loadable_module_get_api_interface(string jarg1); @@ -9082,6 +9207,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_is_number")] public static extern int switch_is_number(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_find_parameter")] + public static extern string switch_find_parameter(string jarg1, string jarg2, HandleRef jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_true")] public static extern int switch_true(string jarg1); @@ -9139,6 +9267,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_clean_name_string")] public static extern string switch_clean_name_string(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_safe_atoi")] + public static extern int switch_safe_atoi(string jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_safe_strdup")] public static extern string switch_safe_strdup(string jarg1); @@ -9271,6 +9402,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_split_user_domain")] public static extern int switch_split_user_domain(string jarg1, ref string jarg2, ref string jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_uuid_str")] + public static extern string switch_uuid_str(string jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_format_number")] + public static extern string switch_format_number(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_profile_node_t_var_set")] public static extern void profile_node_t_var_set(HandleRef jarg1, string jarg2); @@ -9505,6 +9642,24 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_caller_profile_soft_get")] public static extern IntPtr switch_caller_profile_soft_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_caller_profile_uuid_str_set")] + public static extern void switch_caller_profile_uuid_str_set(HandleRef jarg1, string jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_caller_profile_uuid_str_get")] + public static extern string switch_caller_profile_uuid_str_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_caller_profile_clone_of_set")] + public static extern void switch_caller_profile_clone_of_set(HandleRef jarg1, string jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_caller_profile_clone_of_get")] + public static extern string switch_caller_profile_clone_of_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_caller_profile_transfer_source_set")] + public static extern void switch_caller_profile_transfer_source_set(HandleRef jarg1, string jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_caller_profile_transfer_source_get")] + public static extern string switch_caller_profile_transfer_source_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_new_switch_caller_profile")] public static extern IntPtr new_switch_caller_profile(); @@ -11632,6 +11787,78 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_delete_switch_application_interface")] public static extern void delete_switch_application_interface(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_interface_name_set")] + public static extern void switch_chat_application_interface_interface_name_set(HandleRef jarg1, string jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_interface_name_get")] + public static extern string switch_chat_application_interface_interface_name_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_chat_application_function_set")] + public static extern void switch_chat_application_interface_chat_application_function_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_chat_application_function_get")] + public static extern IntPtr switch_chat_application_interface_chat_application_function_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_long_desc_set")] + public static extern void switch_chat_application_interface_long_desc_set(HandleRef jarg1, string jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_long_desc_get")] + public static extern string switch_chat_application_interface_long_desc_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_short_desc_set")] + public static extern void switch_chat_application_interface_short_desc_set(HandleRef jarg1, string jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_short_desc_get")] + public static extern string switch_chat_application_interface_short_desc_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_syntax_set")] + public static extern void switch_chat_application_interface_syntax_set(HandleRef jarg1, string jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_syntax_get")] + public static extern string switch_chat_application_interface_syntax_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_flags_set")] + public static extern void switch_chat_application_interface_flags_set(HandleRef jarg1, uint jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_flags_get")] + public static extern uint switch_chat_application_interface_flags_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_rwlock_set")] + public static extern void switch_chat_application_interface_rwlock_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_rwlock_get")] + public static extern IntPtr switch_chat_application_interface_rwlock_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_refs_set")] + public static extern void switch_chat_application_interface_refs_set(HandleRef jarg1, int jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_refs_get")] + public static extern int switch_chat_application_interface_refs_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_reflock_set")] + public static extern void switch_chat_application_interface_reflock_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_reflock_get")] + public static extern IntPtr switch_chat_application_interface_reflock_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_parent_set")] + public static extern void switch_chat_application_interface_parent_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_parent_get")] + public static extern IntPtr switch_chat_application_interface_parent_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_next_set")] + public static extern void switch_chat_application_interface_next_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_chat_application_interface_next_get")] + public static extern IntPtr switch_chat_application_interface_next_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_new_switch_chat_application_interface")] + public static extern IntPtr new_switch_chat_application_interface(); + + [DllImport("mod_managed", EntryPoint="CSharp_delete_switch_chat_application_interface")] + public static extern void delete_switch_chat_application_interface(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_api_interface_interface_name_set")] public static extern void switch_api_interface_interface_name_set(HandleRef jarg1, string jarg2); @@ -11917,6 +12144,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_hold_music_partner")] public static extern string switch_channel_get_hold_music_partner(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_del_variable_prefix")] + public static extern uint switch_channel_del_variable_prefix(HandleRef jarg1, string jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_export_variable_var_check")] public static extern int switch_channel_export_variable_var_check(HandleRef jarg1, string jarg2, string jarg3, string jarg4, int jarg5); @@ -12358,6 +12588,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_event_get_header_idx")] public static extern string switch_event_get_header_idx(HandleRef jarg1, string jarg2, int jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_event_rename_header")] + public static extern int switch_event_rename_header(HandleRef jarg1, string jarg2, string jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_event_get_body")] public static extern string switch_event_get_body(HandleRef jarg1); @@ -12382,6 +12615,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_event_merge")] public static extern void switch_event_merge(HandleRef jarg1, HandleRef jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_event_dup_reply")] + public static extern int switch_event_dup_reply(HandleRef jarg1, HandleRef jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_event_fire_detailed")] public static extern int switch_event_fire_detailed(string jarg1, string jarg2, int jarg3, HandleRef jarg4, HandleRef jarg5); @@ -12427,6 +12663,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_event_running")] public static extern int switch_event_running(); + [DllImport("mod_managed", EntryPoint="CSharp_switch_event_set_body")] + public static extern int switch_event_set_body(HandleRef jarg1, string jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_event_expand_headers")] public static extern string switch_event_expand_headers(HandleRef jarg1, string jarg2); @@ -12685,6 +12924,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_collect_digits_count")] public static extern int switch_ivr_collect_digits_count(HandleRef jarg1, string jarg2, HandleRef jarg3, HandleRef jarg4, string jarg5, string jarg6, uint jarg7, uint jarg8, uint jarg9); + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_play_and_detect_speech")] + public static extern int switch_ivr_play_and_detect_speech(HandleRef jarg1, string jarg2, string jarg3, string jarg4, ref string jarg5); + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_detect_speech")] public static extern int switch_ivr_detect_speech(HandleRef jarg1, string jarg2, string jarg3, string jarg4, string jarg5, HandleRef jarg6); @@ -12964,6 +13206,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_uuid_exists")] public static extern int switch_ivr_uuid_exists(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_dmachine_get_name")] + public static extern string switch_ivr_dmachine_get_name(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_dmachine_set_match_callback")] public static extern void switch_ivr_dmachine_set_match_callback(HandleRef jarg1, HandleRef jarg2); @@ -13018,6 +13263,15 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_insert_file")] public static extern int switch_ivr_insert_file(HandleRef jarg1, string jarg2, string jarg3, HandleRef jarg4); + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_create_message_reply")] + public static extern int switch_ivr_create_message_reply(HandleRef jarg1, HandleRef jarg2, string jarg3); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_check_presence_mapping")] + public static extern string switch_ivr_check_presence_mapping(string jarg1, string jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_kill_uuid")] + public static extern int switch_ivr_kill_uuid(string jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_RTP_MAX_BUF_LEN_get")] public static extern int SWITCH_RTP_MAX_BUF_LEN_get(); @@ -13580,7 +13834,7 @@ class freeswitchPINVOKE { public static extern uint switch_xml_parse_section_string(string jarg1); [DllImport("mod_managed", EntryPoint="CSharp_switch_xml_std_datetime_check")] - public static extern int switch_xml_std_datetime_check(HandleRef jarg1); + public static extern int switch_xml_std_datetime_check(HandleRef jarg1, HandleRef jarg2); [DllImport("mod_managed", EntryPoint="CSharp_switch_xml_locate_language")] public static extern int switch_xml_locate_language(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, HandleRef jarg4, HandleRef jarg5, HandleRef jarg6, string jarg7); @@ -14107,6 +14361,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_config_next_pair")] public static extern int switch_config_next_pair(HandleRef jarg1, ref string jarg2, ref string jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_setGlobalVariable")] + public static extern void setGlobalVariable(string jarg1, string jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_getGlobalVariable")] + public static extern string getGlobalVariable(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_consoleLog")] public static extern void consoleLog(string jarg1, string jarg2); @@ -14233,6 +14493,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_delete_Event")] public static extern void delete_Event(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_Event_chat_execute")] + public static extern int Event_chat_execute(HandleRef jarg1, string jarg2, string jarg3); + + [DllImport("mod_managed", EntryPoint="CSharp_Event_chat_send")] + public static extern int Event_chat_send(HandleRef jarg1, string jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_Event_Serialize")] public static extern string Event_Serialize(HandleRef jarg1, string jarg2); @@ -14312,7 +14578,7 @@ class freeswitchPINVOKE { public static extern int EventConsumer_bind(HandleRef jarg1, string jarg2, string jarg3); [DllImport("mod_managed", EntryPoint="CSharp_EventConsumer_pop")] - public static extern IntPtr EventConsumer_pop(HandleRef jarg1, int jarg2); + public static extern IntPtr EventConsumer_pop(HandleRef jarg1, int jarg2, int jarg3); [DllImport("mod_managed", EntryPoint="CSharp_delete_CoreSession")] public static extern void delete_CoreSession(HandleRef jarg1); @@ -16549,6 +16815,36 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; +public class SWIGTYPE_p_f_p_switch_event_p_q_const__char__switch_status_t { + private HandleRef swigCPtr; + + internal SWIGTYPE_p_f_p_switch_event_p_q_const__char__switch_status_t(IntPtr cPtr, bool futureUse) { + swigCPtr = new HandleRef(this, cPtr); + } + + protected SWIGTYPE_p_f_p_switch_event_p_q_const__char__switch_status_t() { + swigCPtr = new HandleRef(null, IntPtr.Zero); + } + + internal static HandleRef getCPtr(SWIGTYPE_p_f_p_switch_event_p_q_const__char__switch_status_t obj) { + return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; + } +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + +using System; +using System.Runtime.InteropServices; + public class SWIGTYPE_p_f_p_switch_event__switch_status_t { private HandleRef swigCPtr; @@ -22247,6 +22543,36 @@ public class switch_caller_profile : IDisposable { } } + public string uuid_str { + set { + freeswitchPINVOKE.switch_caller_profile_uuid_str_set(swigCPtr, value); + } + get { + string ret = freeswitchPINVOKE.switch_caller_profile_uuid_str_get(swigCPtr); + return ret; + } + } + + public string clone_of { + set { + freeswitchPINVOKE.switch_caller_profile_clone_of_set(swigCPtr, value); + } + get { + string ret = freeswitchPINVOKE.switch_caller_profile_clone_of_get(swigCPtr); + return ret; + } + } + + public string transfer_source { + set { + freeswitchPINVOKE.switch_caller_profile_transfer_source_set(swigCPtr, value); + } + get { + string ret = freeswitchPINVOKE.switch_caller_profile_transfer_source_get(swigCPtr); + return ret; + } + } + public switch_caller_profile() : this(freeswitchPINVOKE.new_switch_caller_profile(), true) { } @@ -22379,7 +22705,8 @@ public enum switch_channel_app_flag_t { CF_APP_TAGGED = (1 << 0), CF_APP_T38 = (1 << 1), CF_APP_T38_REQ = (1 << 2), - CF_APP_T38_FAIL = (1 << 3) + CF_APP_T38_FAIL = (1 << 3), + CF_APP_T38_NEGOTIATED = (1 << 4) } } @@ -22492,6 +22819,7 @@ public enum switch_channel_flag_t { CF_BRIDGE_NOWRITE, CF_RECOVERED, CF_JITTERBUFFER, + CF_JITTERBUFFER_PLC, CF_DIALPLAN, CF_BLOCK_BROADCAST_UNTIL_MEDIA, CF_CNG_PLC, @@ -22500,6 +22828,8 @@ public enum switch_channel_flag_t { CF_SIGNAL_DATA, CF_SIMPLIFY, CF_ZOMBIE_EXEC, + CF_INTERCEPT, + CF_INTERCEPTED, CF_FLAG_MAX } @@ -22734,6 +23064,185 @@ public class switch_channel_timetable : IDisposable { namespace FreeSWITCH.Native { +public enum switch_chat_application_flag_enum_t { + SCAF_NONE = 0 +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + +using System; +using System.Runtime.InteropServices; + +public class switch_chat_application_interface : IDisposable { + private HandleRef swigCPtr; + protected bool swigCMemOwn; + + internal switch_chat_application_interface(IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = new HandleRef(this, cPtr); + } + + internal static HandleRef getCPtr(switch_chat_application_interface obj) { + return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; + } + + ~switch_chat_application_interface() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != IntPtr.Zero) { + if (swigCMemOwn) { + swigCMemOwn = false; + freeswitchPINVOKE.delete_switch_chat_application_interface(swigCPtr); + } + swigCPtr = new HandleRef(null, IntPtr.Zero); + } + GC.SuppressFinalize(this); + } + } + + public string interface_name { + set { + freeswitchPINVOKE.switch_chat_application_interface_interface_name_set(swigCPtr, value); + } + get { + string ret = freeswitchPINVOKE.switch_chat_application_interface_interface_name_get(swigCPtr); + return ret; + } + } + + public SWIGTYPE_p_f_p_switch_event_p_q_const__char__switch_status_t chat_application_function { + set { + freeswitchPINVOKE.switch_chat_application_interface_chat_application_function_set(swigCPtr, SWIGTYPE_p_f_p_switch_event_p_q_const__char__switch_status_t.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_chat_application_interface_chat_application_function_get(swigCPtr); + SWIGTYPE_p_f_p_switch_event_p_q_const__char__switch_status_t ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_f_p_switch_event_p_q_const__char__switch_status_t(cPtr, false); + return ret; + } + } + + public string long_desc { + set { + freeswitchPINVOKE.switch_chat_application_interface_long_desc_set(swigCPtr, value); + } + get { + string ret = freeswitchPINVOKE.switch_chat_application_interface_long_desc_get(swigCPtr); + return ret; + } + } + + public string short_desc { + set { + freeswitchPINVOKE.switch_chat_application_interface_short_desc_set(swigCPtr, value); + } + get { + string ret = freeswitchPINVOKE.switch_chat_application_interface_short_desc_get(swigCPtr); + return ret; + } + } + + public string syntax { + set { + freeswitchPINVOKE.switch_chat_application_interface_syntax_set(swigCPtr, value); + } + get { + string ret = freeswitchPINVOKE.switch_chat_application_interface_syntax_get(swigCPtr); + return ret; + } + } + + public uint flags { + set { + freeswitchPINVOKE.switch_chat_application_interface_flags_set(swigCPtr, value); + } + get { + uint ret = freeswitchPINVOKE.switch_chat_application_interface_flags_get(swigCPtr); + return ret; + } + } + + public SWIGTYPE_p_switch_thread_rwlock_t rwlock { + set { + freeswitchPINVOKE.switch_chat_application_interface_rwlock_set(swigCPtr, SWIGTYPE_p_switch_thread_rwlock_t.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_chat_application_interface_rwlock_get(swigCPtr); + SWIGTYPE_p_switch_thread_rwlock_t ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_switch_thread_rwlock_t(cPtr, false); + return ret; + } + } + + public int refs { + set { + freeswitchPINVOKE.switch_chat_application_interface_refs_set(swigCPtr, value); + } + get { + int ret = freeswitchPINVOKE.switch_chat_application_interface_refs_get(swigCPtr); + return ret; + } + } + + public SWIGTYPE_p_switch_mutex_t reflock { + set { + freeswitchPINVOKE.switch_chat_application_interface_reflock_set(swigCPtr, SWIGTYPE_p_switch_mutex_t.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_chat_application_interface_reflock_get(swigCPtr); + SWIGTYPE_p_switch_mutex_t ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_switch_mutex_t(cPtr, false); + return ret; + } + } + + public switch_loadable_module_interface parent { + set { + freeswitchPINVOKE.switch_chat_application_interface_parent_set(swigCPtr, switch_loadable_module_interface.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_chat_application_interface_parent_get(swigCPtr); + switch_loadable_module_interface ret = (cPtr == IntPtr.Zero) ? null : new switch_loadable_module_interface(cPtr, false); + return ret; + } + } + + public switch_chat_application_interface next { + set { + freeswitchPINVOKE.switch_chat_application_interface_next_set(swigCPtr, switch_chat_application_interface.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_chat_application_interface_next_get(swigCPtr); + switch_chat_application_interface ret = (cPtr == IntPtr.Zero) ? null : new switch_chat_application_interface(cPtr, false); + return ret; + } + } + + public switch_chat_application_interface() : this(freeswitchPINVOKE.new_switch_chat_application_interface(), true) { + } + +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + using System; using System.Runtime.InteropServices; @@ -23922,7 +24431,9 @@ namespace FreeSWITCH.Native { SCF_MINIMAL = (1 << 14), SCF_USE_NAT_MAPPING = (1 << 15), SCF_CLEAR_SQL = (1 << 16), - SCF_THREADED_SYSTEM_EXEC = (1 << 17) + SCF_THREADED_SYSTEM_EXEC = (1 << 17), + SCF_SYNC_CLOCK_REQUESTED = (1 << 18), + SCF_CORE_ODBC_REQ = (1 << 19) } } @@ -24231,6 +24742,7 @@ public enum switch_core_session_message_types_t { SWITCH_MESSAGE_INDICATE_JITTER_BUFFER, SWITCH_MESSAGE_INDICATE_RECOVERY_REFRESH, SWITCH_MESSAGE_INDICATE_SIGNAL_DATA, + SWITCH_MESSAGE_INDICATE_INFO, SWITCH_MESSAGE_INVALID } @@ -25525,7 +26037,8 @@ public class switch_event : IDisposable { namespace FreeSWITCH.Native { public enum switch_event_flag_t { - EF_UNIQ_HEADERS = (1 << 0) + EF_UNIQ_HEADERS = (1 << 0), + EF_NO_CHAT_EXEC = (1 << 1) } } @@ -28699,6 +29212,17 @@ public class switch_loadable_module_interface : IDisposable { } } + public switch_chat_application_interface chat_application_interface { + set { + freeswitchPINVOKE.switch_loadable_module_interface_chat_application_interface_set(swigCPtr, switch_chat_application_interface.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_loadable_module_interface_chat_application_interface_get(swigCPtr); + switch_chat_application_interface ret = (cPtr == IntPtr.Zero) ? null : new switch_chat_application_interface(cPtr, false); + return ret; + } + } + public switch_api_interface api_interface { set { freeswitchPINVOKE.switch_loadable_module_interface_api_interface_set(swigCPtr, switch_api_interface.getCPtr(value)); @@ -29240,7 +29764,8 @@ public enum switch_module_interface_name_t { SWITCH_SAY_INTERFACE, SWITCH_ASR_INTERFACE, SWITCH_MANAGEMENT_INTERFACE, - SWITCH_LIMIT_INTERFACE + SWITCH_LIMIT_INTERFACE, + SWITCH_CHAT_APPLICATION_INTERFACE } } @@ -29502,7 +30027,8 @@ public enum switch_rtp_bug_flag_t { RTP_BUG_START_SEQ_AT_ZERO = (1 << 4), RTP_BUG_NEVER_SEND_MARKER = (1 << 5), RTP_BUG_IGNORE_DTMF_DURATION = (1 << 6), - RTP_BUG_ACCEPT_ANY_PACKETS = (1 << 7) + RTP_BUG_ACCEPT_ANY_PACKETS = (1 << 7), + RTP_BUG_GEN_ONE_GEN_ALL = (1 << 8) } } @@ -30351,7 +30877,8 @@ public enum switch_say_method_t { SSM_NA, SSM_PRONOUNCED, SSM_ITERATED, - SSM_COUNTED + SSM_COUNTED, + SSM_PRONOUNCED_YEAR } } @@ -30555,7 +31082,8 @@ public enum switch_session_ctl_t { SCSC_SHUTDOWN_CHECK, SCSC_PAUSE_CHECK, SCSC_READY_CHECK, - SCSC_THREADED_SYSTEM_EXEC + SCSC_THREADED_SYSTEM_EXEC, + SCSC_SYNC_CLOCK_WHEN_IDLE } } @@ -31753,6 +32281,16 @@ public class switch_t38_options_t : IDisposable { } } + public string sdp_o_line { + set { + freeswitchPINVOKE.switch_t38_options_t_sdp_o_line_set(swigCPtr, value); + } + get { + string ret = freeswitchPINVOKE.switch_t38_options_t_sdp_o_line_get(swigCPtr); + return ret; + } + } + public switch_t38_options_t() : this(freeswitchPINVOKE.new_switch_t38_options_t(), true) { } @@ -32626,6 +33164,7 @@ namespace FreeSWITCH.Native { SWITCH_XML_SECTION_DIRECTORY = (1 << 1), SWITCH_XML_SECTION_DIALPLAN = (1 << 2), SWITCH_XML_SECTION_PHRASES = (1 << 3), + SWITCH_XML_SECTION_CHATPLAN = (1 << 4), SWITCH_XML_SECTION_MAX = (1 << 4) } diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs index 3f828e0967..06fb116bb2 100644 --- a/src/mod/languages/mod_managed/managed/swig.cs +++ b/src/mod/languages/mod_managed/managed/swig.cs @@ -650,8 +650,8 @@ public class EventConsumer : IDisposable { return ret; } - public Event pop(int block) { - IntPtr cPtr = freeswitchPINVOKE.EventConsumer_pop(swigCPtr, block); + public Event pop(int block, int timeout) { + IntPtr cPtr = freeswitchPINVOKE.EventConsumer_pop(swigCPtr, block, timeout); Event ret = (cPtr == IntPtr.Zero) ? null : new Event(cPtr, true); return ret; } @@ -1183,16 +1183,6 @@ public class freeswitch { return ret; } - public static int switch_core_curl_count(SWIGTYPE_p_int val) { - int ret = freeswitchPINVOKE.switch_core_curl_count(SWIGTYPE_p_int.getCPtr(val)); - return ret; - } - - public static int switch_core_ssl_count(SWIGTYPE_p_int val) { - int ret = freeswitchPINVOKE.switch_core_ssl_count(SWIGTYPE_p_int.getCPtr(val)); - return ret; - } - public static void switch_core_remove_state_handler(switch_state_handler_table state_handler) { freeswitchPINVOKE.switch_core_remove_state_handler(switch_state_handler_table.getCPtr(state_handler)); } @@ -1212,6 +1202,11 @@ public class freeswitch { return ret; } + public static int switch_core_session_sync_clock() { + int ret = freeswitchPINVOKE.switch_core_session_sync_clock(); + return ret; + } + public static switch_status_t switch_core_perform_destroy_memory_pool(SWIGTYPE_p_p_apr_pool_t pool, string file, string func, int line) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_perform_destroy_memory_pool(SWIGTYPE_p_p_apr_pool_t.getCPtr(pool), file, func, line); return ret; @@ -1792,8 +1787,8 @@ public class freeswitch { return ret; } - public static SWIGTYPE_p_HashElem switch_hash_first(string depricate_me, SWIGTYPE_p_switch_hash hash) { - IntPtr cPtr = freeswitchPINVOKE.switch_hash_first(depricate_me, SWIGTYPE_p_switch_hash.getCPtr(hash)); + public static SWIGTYPE_p_HashElem switch_hash_first(string deprecate_me, SWIGTYPE_p_switch_hash hash) { + IntPtr cPtr = freeswitchPINVOKE.switch_hash_first(deprecate_me, SWIGTYPE_p_switch_hash.getCPtr(hash)); SWIGTYPE_p_HashElem ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_HashElem(cPtr, false); return ret; } @@ -2191,6 +2186,16 @@ public class freeswitch { return ret; } + public static switch_bool_t switch_core_ready_inbound() { + switch_bool_t ret = (switch_bool_t)freeswitchPINVOKE.switch_core_ready_inbound(); + return ret; + } + + public static switch_bool_t switch_core_ready_outbound() { + switch_bool_t ret = (switch_bool_t)freeswitchPINVOKE.switch_core_ready_outbound(); + return ret; + } + public static uint switch_core_flags() { uint ret = freeswitchPINVOKE.switch_core_flags(); return ret; @@ -2981,6 +2986,11 @@ public class freeswitch { return ret; } + public static string switch_find_parameter(string str, string param, SWIGTYPE_p_apr_pool_t pool) { + string ret = freeswitchPINVOKE.switch_find_parameter(str, param, SWIGTYPE_p_apr_pool_t.getCPtr(pool)); + return ret; + } + public static int switch_true(string expr) { int ret = freeswitchPINVOKE.switch_true(expr); return ret; @@ -3079,6 +3089,11 @@ public class freeswitch { return ret; } + public static int switch_safe_atoi(string nptr, int dft) { + int ret = freeswitchPINVOKE.switch_safe_atoi(nptr, dft); + return ret; + } + public static string switch_safe_strdup(string it) { string ret = freeswitchPINVOKE.switch_safe_strdup(it); return ret; @@ -3301,6 +3316,17 @@ public class freeswitch { return ret; } + public static string switch_uuid_str(string buf, SWIGTYPE_p_switch_size_t len) { + string ret = freeswitchPINVOKE.switch_uuid_str(buf, SWIGTYPE_p_switch_size_t.getCPtr(len)); + if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + public static string switch_format_number(string num) { + string ret = freeswitchPINVOKE.switch_format_number(num); + return ret; + } + public static switch_caller_extension switch_caller_extension_new(SWIGTYPE_p_switch_core_session session, string extension_name, string extension_number) { IntPtr cPtr = freeswitchPINVOKE.switch_caller_extension_new(SWIGTYPE_p_switch_core_session.getCPtr(session), extension_name, extension_number); switch_caller_extension ret = (cPtr == IntPtr.Zero) ? null : new switch_caller_extension(cPtr, false); @@ -3539,6 +3565,11 @@ public class freeswitch { return ret; } + public static uint switch_channel_del_variable_prefix(SWIGTYPE_p_switch_channel channel, string prefix) { + uint ret = freeswitchPINVOKE.switch_channel_del_variable_prefix(SWIGTYPE_p_switch_channel.getCPtr(channel), prefix); + return ret; + } + public static switch_status_t switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel channel, string varname, string val, string export_varname, switch_bool_t var_check) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel.getCPtr(channel), varname, val, export_varname, (int)var_check); return ret; @@ -3664,6 +3695,10 @@ public class freeswitch { freeswitchPINVOKE.switch_channel_set_state_flag(SWIGTYPE_p_switch_channel.getCPtr(channel), (int)flag); } + public static void switch_channel_clear_state_flag(SWIGTYPE_p_switch_channel channel, switch_channel_flag_t flag) { + freeswitchPINVOKE.switch_channel_clear_state_flag(SWIGTYPE_p_switch_channel.getCPtr(channel), (int)flag); + } + public static void switch_channel_clear_flag(SWIGTYPE_p_switch_channel channel, switch_channel_flag_t flag) { freeswitchPINVOKE.switch_channel_clear_flag(SWIGTYPE_p_switch_channel.getCPtr(channel), (int)flag); } @@ -4345,6 +4380,11 @@ public class freeswitch { return ret; } + public static switch_status_t switch_ivr_play_and_detect_speech(SWIGTYPE_p_switch_core_session session, string file, string mod_name, string grammar, ref string result) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_play_and_detect_speech(SWIGTYPE_p_switch_core_session.getCPtr(session), file, mod_name, grammar, ref result); + return ret; + } + public static switch_status_t switch_ivr_detect_speech(SWIGTYPE_p_switch_core_session session, string mod_name, string grammar, string name, string dest, switch_asr_handle ah) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_detect_speech(SWIGTYPE_p_switch_core_session.getCPtr(session), mod_name, grammar, name, dest, switch_asr_handle.getCPtr(ah)); return ret; @@ -4809,6 +4849,11 @@ public class freeswitch { return ret; } + public static string switch_ivr_dmachine_get_name(SWIGTYPE_p_switch_ivr_dmachine dmachine) { + string ret = freeswitchPINVOKE.switch_ivr_dmachine_get_name(SWIGTYPE_p_switch_ivr_dmachine.getCPtr(dmachine)); + return ret; + } + public static void switch_ivr_dmachine_set_match_callback(SWIGTYPE_p_switch_ivr_dmachine dmachine, SWIGTYPE_p_f_p_switch_ivr_dmachine_match__switch_status_t match_callback) { freeswitchPINVOKE.switch_ivr_dmachine_set_match_callback(SWIGTYPE_p_switch_ivr_dmachine.getCPtr(dmachine), SWIGTYPE_p_f_p_switch_ivr_dmachine_match__switch_status_t.getCPtr(match_callback)); } @@ -4901,6 +4946,16 @@ public class freeswitch { return ret; } + public static string switch_ivr_check_presence_mapping(string exten_name, string domain_name) { + string ret = freeswitchPINVOKE.switch_ivr_check_presence_mapping(exten_name, domain_name); + return ret; + } + + public static switch_status_t switch_ivr_kill_uuid(string uuid, switch_call_cause_t cause) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_kill_uuid(uuid, (int)cause); + return ret; + } + public static switch_status_t switch_rtp_add_crypto_key(SWIGTYPE_p_switch_rtp rtp_session, switch_rtp_crypto_direction_t direction, uint index, switch_rtp_crypto_key_type_t type, SWIGTYPE_p_unsigned_char key, SWIGTYPE_p_switch_size_t keylen) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_add_crypto_key(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), (int)direction, index, (int)type, SWIGTYPE_p_unsigned_char.getCPtr(key), SWIGTYPE_p_switch_size_t.getCPtr(keylen)); if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); @@ -5507,8 +5562,8 @@ public class freeswitch { return ret; } - public static int switch_xml_std_datetime_check(switch_xml xcond) { - int ret = freeswitchPINVOKE.switch_xml_std_datetime_check(switch_xml.getCPtr(xcond)); + public static int switch_xml_std_datetime_check(switch_xml xcond, SWIGTYPE_p_int offset) { + int ret = freeswitchPINVOKE.switch_xml_std_datetime_check(switch_xml.getCPtr(xcond), SWIGTYPE_p_int.getCPtr(offset)); return ret; } @@ -5685,6 +5740,15 @@ public class freeswitch { return ret; } + public static void setGlobalVariable(string var_name, string var_val) { + freeswitchPINVOKE.setGlobalVariable(var_name, var_val); + } + + public static string getGlobalVariable(string var_name) { + string ret = freeswitchPINVOKE.getGlobalVariable(var_name); + return ret; + } + public static void consoleLog(string level_str, string msg) { freeswitchPINVOKE.consoleLog(level_str, msg); } @@ -5801,6 +5865,8 @@ public class freeswitch { public static readonly string SWITCH_READ_RESULT_VARIABLE = freeswitchPINVOKE.SWITCH_READ_RESULT_VARIABLE_get(); public static readonly string SWITCH_COPY_XML_CDR_VARIABLE = freeswitchPINVOKE.SWITCH_COPY_XML_CDR_VARIABLE_get(); public static readonly string SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE = freeswitchPINVOKE.SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE_get(); + public static readonly string SWITCH_TRANSFER_HISTORY_VARIABLE = freeswitchPINVOKE.SWITCH_TRANSFER_HISTORY_VARIABLE_get(); + public static readonly string SWITCH_TRANSFER_SOURCE_VARIABLE = freeswitchPINVOKE.SWITCH_TRANSFER_SOURCE_VARIABLE_get(); public static readonly string SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE = freeswitchPINVOKE.SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE_get(); public static readonly string SWITCH_CHANNEL_EXECUTE_ON_PRE_ANSWER_VARIABLE = freeswitchPINVOKE.SWITCH_CHANNEL_EXECUTE_ON_PRE_ANSWER_VARIABLE_get(); public static readonly string SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE = freeswitchPINVOKE.SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE_get(); @@ -6346,6 +6412,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE_get")] public static extern string SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE_get(); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_TRANSFER_HISTORY_VARIABLE_get")] + public static extern string SWITCH_TRANSFER_HISTORY_VARIABLE_get(); + + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_TRANSFER_SOURCE_VARIABLE_get")] + public static extern string SWITCH_TRANSFER_SOURCE_VARIABLE_get(); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE_get")] public static extern string SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE_get(); @@ -7078,6 +7150,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_t38_options_t_local_port_get")] public static extern ushort switch_t38_options_t_local_port_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_t38_options_t_sdp_o_line_set")] + public static extern void switch_t38_options_t_sdp_o_line_set(HandleRef jarg1, string jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_t38_options_t_sdp_o_line_get")] + public static extern string switch_t38_options_t_sdp_o_line_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_new_switch_t38_options_t")] public static extern IntPtr new_switch_t38_options_t(); @@ -7831,12 +7909,6 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_add_state_handler")] public static extern int switch_core_add_state_handler(HandleRef jarg1); - [DllImport("mod_managed", EntryPoint="CSharp_switch_core_curl_count")] - public static extern int switch_core_curl_count(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_core_ssl_count")] - public static extern int switch_core_ssl_count(HandleRef jarg1); - [DllImport("mod_managed", EntryPoint="CSharp_switch_core_remove_state_handler")] public static extern void switch_core_remove_state_handler(HandleRef jarg1); @@ -7849,6 +7921,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_perform_new_memory_pool")] public static extern int switch_core_perform_new_memory_pool(HandleRef jarg1, string jarg2, string jarg3, int jarg4); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_sync_clock")] + public static extern int switch_core_session_sync_clock(); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_perform_destroy_memory_pool")] public static extern int switch_core_perform_destroy_memory_pool(HandleRef jarg1, string jarg2, string jarg3, int jarg4); @@ -8440,6 +8515,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_ready")] public static extern int switch_core_ready(); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_ready_inbound")] + public static extern int switch_core_ready_inbound(); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_ready_outbound")] + public static extern int switch_core_ready_outbound(); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_flags")] public static extern uint switch_core_flags(); @@ -9136,6 +9217,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_is_number")] public static extern int switch_is_number(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_find_parameter")] + public static extern string switch_find_parameter(string jarg1, string jarg2, HandleRef jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_true")] public static extern int switch_true(string jarg1); @@ -9193,6 +9277,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_clean_name_string")] public static extern string switch_clean_name_string(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_safe_atoi")] + public static extern int switch_safe_atoi(string jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_safe_strdup")] public static extern string switch_safe_strdup(string jarg1); @@ -9325,6 +9412,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_split_user_domain")] public static extern int switch_split_user_domain(string jarg1, ref string jarg2, ref string jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_uuid_str")] + public static extern string switch_uuid_str(string jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_format_number")] + public static extern string switch_format_number(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_profile_node_t_var_set")] public static extern void profile_node_t_var_set(HandleRef jarg1, string jarg2); @@ -9559,6 +9652,24 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_caller_profile_soft_get")] public static extern IntPtr switch_caller_profile_soft_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_caller_profile_uuid_str_set")] + public static extern void switch_caller_profile_uuid_str_set(HandleRef jarg1, string jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_caller_profile_uuid_str_get")] + public static extern string switch_caller_profile_uuid_str_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_caller_profile_clone_of_set")] + public static extern void switch_caller_profile_clone_of_set(HandleRef jarg1, string jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_caller_profile_clone_of_get")] + public static extern string switch_caller_profile_clone_of_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_caller_profile_transfer_source_set")] + public static extern void switch_caller_profile_transfer_source_set(HandleRef jarg1, string jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_caller_profile_transfer_source_get")] + public static extern string switch_caller_profile_transfer_source_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_new_switch_caller_profile")] public static extern IntPtr new_switch_caller_profile(); @@ -12043,6 +12154,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_hold_music_partner")] public static extern string switch_channel_get_hold_music_partner(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_del_variable_prefix")] + public static extern uint switch_channel_del_variable_prefix(HandleRef jarg1, string jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_export_variable_var_check")] public static extern int switch_channel_export_variable_var_check(HandleRef jarg1, string jarg2, string jarg3, string jarg4, int jarg5); @@ -12124,6 +12238,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_set_state_flag")] public static extern void switch_channel_set_state_flag(HandleRef jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_clear_state_flag")] + public static extern void switch_channel_clear_state_flag(HandleRef jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_clear_flag")] public static extern void switch_channel_clear_flag(HandleRef jarg1, int jarg2); @@ -12820,6 +12937,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_collect_digits_count")] public static extern int switch_ivr_collect_digits_count(HandleRef jarg1, string jarg2, HandleRef jarg3, HandleRef jarg4, string jarg5, string jarg6, uint jarg7, uint jarg8, uint jarg9); + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_play_and_detect_speech")] + public static extern int switch_ivr_play_and_detect_speech(HandleRef jarg1, string jarg2, string jarg3, string jarg4, ref string jarg5); + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_detect_speech")] public static extern int switch_ivr_detect_speech(HandleRef jarg1, string jarg2, string jarg3, string jarg4, string jarg5, HandleRef jarg6); @@ -13099,6 +13219,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_uuid_exists")] public static extern int switch_ivr_uuid_exists(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_dmachine_get_name")] + public static extern string switch_ivr_dmachine_get_name(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_dmachine_set_match_callback")] public static extern void switch_ivr_dmachine_set_match_callback(HandleRef jarg1, HandleRef jarg2); @@ -13156,6 +13279,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_create_message_reply")] public static extern int switch_ivr_create_message_reply(HandleRef jarg1, HandleRef jarg2, string jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_check_presence_mapping")] + public static extern string switch_ivr_check_presence_mapping(string jarg1, string jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_kill_uuid")] + public static extern int switch_ivr_kill_uuid(string jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_RTP_MAX_BUF_LEN_get")] public static extern int SWITCH_RTP_MAX_BUF_LEN_get(); @@ -13718,7 +13847,7 @@ class freeswitchPINVOKE { public static extern uint switch_xml_parse_section_string(string jarg1); [DllImport("mod_managed", EntryPoint="CSharp_switch_xml_std_datetime_check")] - public static extern int switch_xml_std_datetime_check(HandleRef jarg1); + public static extern int switch_xml_std_datetime_check(HandleRef jarg1, HandleRef jarg2); [DllImport("mod_managed", EntryPoint="CSharp_switch_xml_locate_language")] public static extern int switch_xml_locate_language(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, HandleRef jarg4, HandleRef jarg5, HandleRef jarg6, string jarg7); @@ -14245,6 +14374,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_config_next_pair")] public static extern int switch_config_next_pair(HandleRef jarg1, ref string jarg2, ref string jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_setGlobalVariable")] + public static extern void setGlobalVariable(string jarg1, string jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_getGlobalVariable")] + public static extern string getGlobalVariable(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_consoleLog")] public static extern void consoleLog(string jarg1, string jarg2); @@ -14456,7 +14591,7 @@ class freeswitchPINVOKE { public static extern int EventConsumer_bind(HandleRef jarg1, string jarg2, string jarg3); [DllImport("mod_managed", EntryPoint="CSharp_EventConsumer_pop")] - public static extern IntPtr EventConsumer_pop(HandleRef jarg1, int jarg2); + public static extern IntPtr EventConsumer_pop(HandleRef jarg1, int jarg2, int jarg3); [DllImport("mod_managed", EntryPoint="CSharp_delete_CoreSession")] public static extern void delete_CoreSession(HandleRef jarg1); @@ -21844,7 +21979,11 @@ public enum switch_call_cause_t { SWITCH_CAUSE_MEDIA_TIMEOUT = 604, SWITCH_CAUSE_PICKED_OFF = 605, SWITCH_CAUSE_USER_NOT_REGISTERED = 606, - SWITCH_CAUSE_PROGRESS_TIMEOUT = 607 + SWITCH_CAUSE_PROGRESS_TIMEOUT = 607, + SWITCH_CAUSE_INVALID_GATEWAY = 608, + SWITCH_CAUSE_GATEWAY_DOWN = 609, + SWITCH_CAUSE_INVALID_URL = 610, + SWITCH_CAUSE_INVALID_PROFILE = 611 } } @@ -22475,6 +22614,36 @@ public class switch_caller_profile : IDisposable { } } + public string uuid_str { + set { + freeswitchPINVOKE.switch_caller_profile_uuid_str_set(swigCPtr, value); + } + get { + string ret = freeswitchPINVOKE.switch_caller_profile_uuid_str_get(swigCPtr); + return ret; + } + } + + public string clone_of { + set { + freeswitchPINVOKE.switch_caller_profile_clone_of_set(swigCPtr, value); + } + get { + string ret = freeswitchPINVOKE.switch_caller_profile_clone_of_get(swigCPtr); + return ret; + } + } + + public string transfer_source { + set { + freeswitchPINVOKE.switch_caller_profile_transfer_source_set(swigCPtr, value); + } + get { + string ret = freeswitchPINVOKE.switch_caller_profile_transfer_source_get(swigCPtr); + return ret; + } + } + public switch_caller_profile() : this(freeswitchPINVOKE.new_switch_caller_profile(), true) { } @@ -22513,7 +22682,8 @@ public enum switch_channel_app_flag_t { CF_APP_TAGGED = (1 << 0), CF_APP_T38 = (1 << 1), CF_APP_T38_REQ = (1 << 2), - CF_APP_T38_FAIL = (1 << 3) + CF_APP_T38_FAIL = (1 << 3), + CF_APP_T38_NEGOTIATED = (1 << 4) } } @@ -22626,6 +22796,7 @@ public enum switch_channel_flag_t { CF_BRIDGE_NOWRITE, CF_RECOVERED, CF_JITTERBUFFER, + CF_JITTERBUFFER_PLC, CF_DIALPLAN, CF_BLOCK_BROADCAST_UNTIL_MEDIA, CF_CNG_PLC, @@ -22634,6 +22805,8 @@ public enum switch_channel_flag_t { CF_SIGNAL_DATA, CF_SIMPLIFY, CF_ZOMBIE_EXEC, + CF_INTERCEPT, + CF_INTERCEPTED, CF_FLAG_MAX } @@ -24197,23 +24370,27 @@ namespace FreeSWITCH.Native { [System.Flags] public enum switch_core_flag_enum_t { SCF_NONE = 0, SCF_USE_SQL = (1 << 0), - SCF_NO_NEW_SESSIONS = (1 << 1), - SCF_SHUTTING_DOWN = (1 << 2), - SCF_VG = (1 << 3), - SCF_RESTART = (1 << 4), - SCF_SHUTDOWN_REQUESTED = (1 << 5), - SCF_USE_AUTO_NAT = (1 << 6), - SCF_EARLY_HANGUP = (1 << 7), - SCF_CALIBRATE_CLOCK = (1 << 8), - SCF_USE_HEAVY_TIMING = (1 << 9), - SCF_USE_CLOCK_RT = (1 << 10), - SCF_VERBOSE_EVENTS = (1 << 11), - SCF_USE_WIN32_MONOTONIC = (1 << 12), - SCF_AUTO_SCHEMAS = (1 << 13), - SCF_MINIMAL = (1 << 14), - SCF_USE_NAT_MAPPING = (1 << 15), - SCF_CLEAR_SQL = (1 << 16), - SCF_THREADED_SYSTEM_EXEC = (1 << 17) + SCF_NO_NEW_OUTBOUND_SESSIONS = (1 << 1), + SCF_NO_NEW_INBOUND_SESSIONS = (1 << 2), + SCF_NO_NEW_SESSIONS = (SCF_NO_NEW_OUTBOUND_SESSIONS|SCF_NO_NEW_INBOUND_SESSIONS), + SCF_SHUTTING_DOWN = (1 << 3), + SCF_VG = (1 << 4), + SCF_RESTART = (1 << 5), + SCF_SHUTDOWN_REQUESTED = (1 << 6), + SCF_USE_AUTO_NAT = (1 << 7), + SCF_EARLY_HANGUP = (1 << 8), + SCF_CALIBRATE_CLOCK = (1 << 9), + SCF_USE_HEAVY_TIMING = (1 << 10), + SCF_USE_CLOCK_RT = (1 << 11), + SCF_VERBOSE_EVENTS = (1 << 12), + SCF_USE_WIN32_MONOTONIC = (1 << 13), + SCF_AUTO_SCHEMAS = (1 << 14), + SCF_MINIMAL = (1 << 15), + SCF_USE_NAT_MAPPING = (1 << 16), + SCF_CLEAR_SQL = (1 << 17), + SCF_THREADED_SYSTEM_EXEC = (1 << 18), + SCF_SYNC_CLOCK_REQUESTED = (1 << 19), + SCF_CORE_ODBC_REQ = (1 << 20) } } @@ -24520,6 +24697,8 @@ public enum switch_core_session_message_types_t { SWITCH_MESSAGE_INDICATE_JITTER_BUFFER, SWITCH_MESSAGE_INDICATE_RECOVERY_REFRESH, SWITCH_MESSAGE_INDICATE_SIGNAL_DATA, + SWITCH_MESSAGE_INDICATE_INFO, + SWITCH_MESSAGE_INDICATE_AUDIO_DATA, SWITCH_MESSAGE_INVALID } @@ -29403,7 +29582,8 @@ namespace FreeSWITCH.Native { SMBF_ANSWER_REQ = (1 << 6), SMBF_THREAD_LOCK = (1 << 7), SMBF_PRUNE = (1 << 8), - SMBF_NO_PAUSE = (1 << 9) + SMBF_NO_PAUSE = (1 << 9), + SMBF_STEREO_SWAP = (1 << 10) } } @@ -29730,7 +29910,8 @@ public enum switch_rtp_bug_flag_t { RTP_BUG_START_SEQ_AT_ZERO = (1 << 4), RTP_BUG_NEVER_SEND_MARKER = (1 << 5), RTP_BUG_IGNORE_DTMF_DURATION = (1 << 6), - RTP_BUG_ACCEPT_ANY_PACKETS = (1 << 7) + RTP_BUG_ACCEPT_ANY_PACKETS = (1 << 7), + RTP_BUG_GEN_ONE_GEN_ALL = (1 << 8) } } @@ -30567,7 +30748,8 @@ public enum switch_say_method_t { SSM_NA, SSM_PRONOUNCED, SSM_ITERATED, - SSM_COUNTED + SSM_COUNTED, + SSM_PRONOUNCED_YEAR } } @@ -30742,6 +30924,8 @@ namespace FreeSWITCH.Native { public enum switch_session_ctl_t { SCSC_PAUSE_INBOUND, + SCSC_PAUSE_OUTBOUND, + SCSC_PAUSE_ALL, SCSC_HUPALL, SCSC_SHUTDOWN, SCSC_CHECK_RUNNING, @@ -30767,9 +30951,12 @@ public enum switch_session_ctl_t { SCSC_MIN_IDLE_CPU, SCSC_VERBOSE_EVENTS, SCSC_SHUTDOWN_CHECK, + SCSC_PAUSE_INBOUND_CHECK, + SCSC_PAUSE_OUTBOUND_CHECK, SCSC_PAUSE_CHECK, SCSC_READY_CHECK, - SCSC_THREADED_SYSTEM_EXEC + SCSC_THREADED_SYSTEM_EXEC, + SCSC_SYNC_CLOCK_WHEN_IDLE } } @@ -31955,6 +32142,16 @@ public class switch_t38_options_t : IDisposable { } } + public string sdp_o_line { + set { + freeswitchPINVOKE.switch_t38_options_t_sdp_o_line_set(swigCPtr, value); + } + get { + string ret = freeswitchPINVOKE.switch_t38_options_t_sdp_o_line_get(swigCPtr); + return ret; + } + } + public switch_t38_options_t() : this(freeswitchPINVOKE.new_switch_t38_options_t(), true) { } @@ -32820,6 +33017,7 @@ namespace FreeSWITCH.Native { SWITCH_XML_SECTION_DIRECTORY = (1 << 1), SWITCH_XML_SECTION_DIALPLAN = (1 << 2), SWITCH_XML_SECTION_PHRASES = (1 << 3), + SWITCH_XML_SECTION_CHATPLAN = (1 << 4), SWITCH_XML_SECTION_MAX = (1 << 4) } diff --git a/src/mod/languages/mod_managed/mod_managed.cpp b/src/mod/languages/mod_managed/mod_managed.cpp index ec2d8663e3..ee6e87a5fc 100644 --- a/src/mod/languages/mod_managed/mod_managed.cpp +++ b/src/mod/languages/mod_managed/mod_managed.cpp @@ -23,7 +23,7 @@ * * Contributor(s): * - * Michael Giagnocavo + * Michael Giagnocavo * David Brazier * Jeff Lenk * @@ -55,6 +55,7 @@ SWITCH_STANDARD_API(managedrun_api_function); /* ExecuteBackground */ SWITCH_STANDARD_API(managed_api_function); /* Execute */ SWITCH_STANDARD_APP(managed_app_function); /* Run */ SWITCH_STANDARD_API(managedreload_api_function); /* Reload */ +SWITCH_STANDARD_API(managedlist_api_function); /* List modules */ #define MOD_MANAGED_ASM_NAME "FreeSWITCH.Managed" #define MOD_MANAGED_ASM_V1 1 @@ -72,19 +73,23 @@ typedef int (*runFunction)(const char *data, void *sessionPtr); typedef int (*executeFunction)(const char *cmd, void *stream, void *Event); typedef int (*executeBackgroundFunction)(const char* cmd); typedef int (*reloadFunction)(const char* cmd); +typedef int (*listFunction)(const char* cmd); static runFunction runDelegate; static executeFunction executeDelegate; static executeBackgroundFunction executeBackgroundDelegate; static reloadFunction reloadDelegate; +static listFunction listDelegate; -SWITCH_MOD_DECLARE_NONSTD(void) InitManagedDelegates(runFunction run, executeFunction execute, executeBackgroundFunction executeBackground, reloadFunction reload) +SWITCH_MOD_DECLARE_NONSTD(void) InitManagedDelegates(runFunction run, executeFunction execute, executeBackgroundFunction executeBackground, reloadFunction reload, listFunction list) { runDelegate = run; executeDelegate = execute; executeBackgroundDelegate = executeBackground; reloadDelegate = reload; + listDelegate = list; } + // Sets up delegates (and anything else needed) on the ManagedSession object // Called from ManagedSession.Initialize Managed -> this is Unmanaged code so all pointers are marshalled and prevented from GC // Exported method. @@ -190,6 +195,7 @@ switch_status_t loadRuntime() // So linux can find the .so char xmlConfig[300]; switch_snprintf(xmlConfig, 300, "", SWITCH_GLOBAL_dirs.mod_dir, SWITCH_PATH_SEPARATOR); + mono_config_parse(NULL); mono_config_parse_memory(xmlConfig); #endif @@ -208,18 +214,13 @@ switch_status_t loadRuntime() } /* Already loaded? */ - MonoAssemblyName name; - name.name = MOD_MANAGED_ASM_NAME; - name.major = MOD_MANAGED_ASM_V1; - name.minor = MOD_MANAGED_ASM_V2; - name.revision = MOD_MANAGED_ASM_V3; - name.build = MOD_MANAGED_ASM_V4; - name.culture = ""; - name.hash_value = ""; - + MonoAssemblyName *name = mono_assembly_name_new (MOD_MANAGED_ASM_NAME); + //Note also that it can't be allocated on the stack anymore and you'll need to create and destroy it with the following API: + //mono_assembly_name_free (name); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Calling mono_assembly_loaded.\n"); - if (!(globals.mod_mono_asm = mono_assembly_loaded(&name))) { + if (!(globals.mod_mono_asm = mono_assembly_loaded(name))) { /* Open the assembly */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Calling mono_domain_assembly_open.\n"); globals.mod_mono_asm = mono_domain_assembly_open(globals.domain, filename); @@ -365,6 +366,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_managed_load) SWITCH_ADD_API(api_interface, "managed", "Run a module as an API function (Execute)", managed_api_function, " []"); SWITCH_ADD_APP(app_interface, "managed", "Run CLI App", "Run an App on a channel", managed_app_function, " []", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_API(api_interface, "managedreload", "Force [re]load of a file", managedreload_api_function, ""); + SWITCH_ADD_API(api_interface, "managedlist", "Log the list of available APIs and Apps", managedlist_api_function, ""); return SWITCH_STATUS_NOUNLOAD; } @@ -444,4 +446,16 @@ SWITCH_STANDARD_API(managedreload_api_function) return SWITCH_STATUS_SUCCESS; } +SWITCH_STANDARD_API(managedlist_api_function) +{ +#ifndef _MANAGED + mono_thread_attach(globals.domain); +#endif + listDelegate(cmd); +#ifndef _MANAGED + mono_thread_detach(mono_thread_current()); +#endif + return SWITCH_STATUS_SUCCESS; +} + SWITCH_END_EXTERN_C diff --git a/src/mod/languages/mod_managed/switch_platform.i b/src/mod/languages/mod_managed/switch_platform.i index 60863e38f3..db5ef6e6bf 100644 --- a/src/mod/languages/mod_managed/switch_platform.i +++ b/src/mod/languages/mod_managed/switch_platform.i @@ -1,4 +1,5 @@ // MANUALLY GENERATED +%include ../../../../swig_common.i typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned long uint32_t; diff --git a/src/mod/languages/mod_perl/freeswitch.i b/src/mod/languages/mod_perl/freeswitch.i index 8c82b28fc6..a02d4476c6 100644 --- a/src/mod/languages/mod_perl/freeswitch.i +++ b/src/mod/languages/mod_perl/freeswitch.i @@ -1,4 +1,5 @@ %module freeswitch +%include ../../../../swig_common.i //%include "cstring.i" /** diff --git a/src/mod/languages/mod_perl/freeswitch.pm b/src/mod/languages/mod_perl/freeswitch.pm index 0e45a5e13a..ffae0be801 100644 --- a/src/mod/languages/mod_perl/freeswitch.pm +++ b/src/mod/languages/mod_perl/freeswitch.pm @@ -48,6 +48,8 @@ sub this { package freeswitch; +*setGlobalVariable = *freeswitchc::setGlobalVariable; +*getGlobalVariable = *freeswitchc::getGlobalVariable; *consoleLog = *freeswitchc::consoleLog; *consoleCleanLog = *freeswitchc::consoleCleanLog; *email = *freeswitchc::email; diff --git a/src/mod/languages/mod_perl/mod_perl.c b/src/mod/languages/mod_perl/mod_perl.c index 55bc44f2de..e658a0892c 100644 --- a/src/mod/languages/mod_perl/mod_perl.c +++ b/src/mod/languages/mod_perl/mod_perl.c @@ -234,6 +234,7 @@ struct perl_o { switch_stream_handle_t *stream; switch_core_session_t *session; char *cmd; + switch_event_t *message; int d; }; @@ -247,6 +248,7 @@ static void *SWITCH_THREAD_FUNC perl_thread_run(switch_thread_t *thread, void *o char *cmd = po->cmd; switch_stream_handle_t *stream = po->stream; switch_core_session_t *session = po->session; + switch_event_t *message = po->message; if (session) { uuid = switch_core_session_get_uuid(session); @@ -271,6 +273,11 @@ static void *SWITCH_THREAD_FUNC perl_thread_run(switch_thread_t *thread, void *o mod_perl_conjure_event(my_perl, stream->param_event, "env"); } } + + if (message) { + mod_perl_conjure_event(my_perl, message, "message"); + } + //Perl_safe_eval(my_perl, cmd); perl_parse_and_execute(my_perl, cmd, NULL); } @@ -432,6 +439,27 @@ static switch_xml_t perl_fetch(const char *section, return xml; } + +SWITCH_STANDARD_CHAT_APP(perl_chat_function) +{ + + struct perl_o po = { 0 }; + + if (zstr(data)) { + return SWITCH_STATUS_FALSE; + } + + po.cmd = strdup(data); + po.stream = NULL; + po.session = NULL; + po.message = message; + perl_thread_run(NULL, &po); + + return SWITCH_STATUS_SUCCESS; + +} + + static switch_status_t do_config(void) { char *cf = "perl.conf"; diff --git a/src/mod/languages/mod_perl/mod_perl_wrap.cpp b/src/mod/languages/mod_perl/mod_perl_wrap.cpp index 3b1165bc7e..a3855445a4 100644 --- a/src/mod/languages/mod_perl/mod_perl_wrap.cpp +++ b/src/mod/languages/mod_perl/mod_perl_wrap.cpp @@ -1566,6 +1566,26 @@ SWIG_AsCharPtrAndSize(SV *obj, char** cptr, size_t* psize, int *alloc) +SWIGINTERNINLINE SV * +SWIG_FromCharPtrAndSize(const char* carray, size_t size) +{ + SV *obj = sv_newmortal(); + if (carray) { + sv_setpvn(obj, carray, size); + } else { + sv_setsv(obj, &PL_sv_undef); + } + return obj; +} + + +SWIGINTERNINLINE SV * +SWIG_FromCharPtr(const char *cptr) +{ + return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0)); +} + + SWIGINTERNINLINE SV * SWIG_From_bool SWIG_PERL_DECL_ARGS_1(bool value) { @@ -1707,26 +1727,6 @@ SWIG_AsVal_int SWIG_PERL_DECL_ARGS_2(SV * obj, int *val) } -SWIGINTERNINLINE SV * -SWIG_FromCharPtrAndSize(const char* carray, size_t size) -{ - SV *obj = sv_newmortal(); - if (carray) { - sv_setpvn(obj, carray, size); - } else { - sv_setsv(obj, &PL_sv_undef); - } - return obj; -} - - -SWIGINTERNINLINE SV * -SWIG_FromCharPtr(const char *cptr) -{ - return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0)); -} - - SWIGINTERNINLINE SV * SWIG_From_long SWIG_PERL_DECL_ARGS_1(long value) { @@ -1915,6 +1915,75 @@ SWIGCLASS_STATIC int swig_magic_readonly(pTHX_ SV *SWIGUNUSEDPARM(sv), MAGIC *SW #ifdef __cplusplus extern "C" { #endif +XS(_wrap_setGlobalVariable) { + { + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 2) || (items > 2)) { + SWIG_croak("Usage: setGlobalVariable(var_name,var_val);"); + } + res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "setGlobalVariable" "', argument " "1"" of type '" "char *""'"); + } + arg1 = reinterpret_cast< char * >(buf1); + res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "setGlobalVariable" "', argument " "2"" of type '" "char *""'"); + } + arg2 = reinterpret_cast< char * >(buf2); + setGlobalVariable(arg1,arg2); + + if (alloc1 == SWIG_NEWOBJ) delete[] buf1; + if (alloc2 == SWIG_NEWOBJ) delete[] buf2; + XSRETURN(argvi); + fail: + if (alloc1 == SWIG_NEWOBJ) delete[] buf1; + if (alloc2 == SWIG_NEWOBJ) delete[] buf2; + SWIG_croak_null(); + } +} + + +XS(_wrap_getGlobalVariable) { + { + char *arg1 = (char *) 0 ; + char *result = 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 1) || (items > 1)) { + SWIG_croak("Usage: getGlobalVariable(var_name);"); + } + res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "getGlobalVariable" "', argument " "1"" of type '" "char *""'"); + } + arg1 = reinterpret_cast< char * >(buf1); + result = (char *)getGlobalVariable(arg1); + ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ; + if (alloc1 == SWIG_NEWOBJ) delete[] buf1; + free(result); + XSRETURN(argvi); + fail: + if (alloc1 == SWIG_NEWOBJ) delete[] buf1; + SWIG_croak_null(); + } +} + + XS(_wrap_consoleLog) { { char *arg1 = (char *) 0 ; @@ -4730,16 +4799,19 @@ XS(_wrap_EventConsumer_pop) { { EventConsumer *arg1 = (EventConsumer *) 0 ; int arg2 = (int) 0 ; + int arg3 = (int) 0 ; Event *result = 0 ; void *argp1 = 0 ; int res1 = 0 ; int val2 ; int ecode2 = 0 ; + int val3 ; + int ecode3 = 0 ; int argvi = 0; dXSARGS; - if ((items < 1) || (items > 2)) { - SWIG_croak("Usage: EventConsumer_pop(self,block);"); + if ((items < 1) || (items > 3)) { + SWIG_croak("Usage: EventConsumer_pop(self,block,timeout);"); } res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_EventConsumer, 0 | 0 ); if (!SWIG_IsOK(res1)) { @@ -4753,14 +4825,23 @@ XS(_wrap_EventConsumer_pop) { } arg2 = static_cast< int >(val2); } - result = (Event *)(arg1)->pop(arg2); + if (items > 2) { + ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "EventConsumer_pop" "', argument " "3"" of type '" "int""'"); + } + arg3 = static_cast< int >(val3); + } + result = (Event *)(arg1)->pop(arg2,arg3); ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Event, SWIG_OWNER | SWIG_SHADOW); argvi++ ; + XSRETURN(argvi); fail: + SWIG_croak_null(); } } @@ -9545,6 +9626,8 @@ static swig_variable_info swig_variables[] = { {0,0,0,0} }; static swig_command_info swig_commands[] = { +{"freeswitchc::setGlobalVariable", _wrap_setGlobalVariable}, +{"freeswitchc::getGlobalVariable", _wrap_getGlobalVariable}, {"freeswitchc::consoleLog", _wrap_consoleLog}, {"freeswitchc::consoleCleanLog", _wrap_consoleCleanLog}, {"freeswitchc::email", _wrap_email}, diff --git a/src/mod/languages/mod_python/freeswitch.py b/src/mod/languages/mod_python/freeswitch.py index c43fc8f3b8..1df258dc0c 100644 --- a/src/mod/languages/mod_python/freeswitch.py +++ b/src/mod/languages/mod_python/freeswitch.py @@ -48,6 +48,8 @@ except AttributeError: del types +setGlobalVariable = _freeswitch.setGlobalVariable +getGlobalVariable = _freeswitch.getGlobalVariable consoleLog = _freeswitch.consoleLog consoleCleanLog = _freeswitch.consoleCleanLog email = _freeswitch.email diff --git a/src/mod/languages/mod_python/mod_python.c b/src/mod/languages/mod_python/mod_python.c index 78caf3b04f..b92526e135 100644 --- a/src/mod/languages/mod_python/mod_python.c +++ b/src/mod/languages/mod_python/mod_python.c @@ -26,12 +26,14 @@ * Brian Fertig * Johny Kadarisman * Traun Leyden + * Heimo Stieg * * mod_python.c -- Python Module * */ #include +#include #ifndef _REENTRANT #define _REENTRANT @@ -43,6 +45,7 @@ #include #include "mod_python_extra.h" +#include PyThreadState *mainThreadState = NULL; @@ -50,6 +53,7 @@ void init_freeswitch(void); int py_thread(const char *text); static void set_max_recursion_depth(void); static switch_api_interface_t python_run_interface; +static void print_python_error(const char * script); SWITCH_MODULE_LOAD_FUNCTION(mod_python_load); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_python_shutdown); @@ -70,6 +74,100 @@ struct switch_py_thread { struct switch_py_thread *thread_pool_head = NULL; static switch_mutex_t *THREAD_POOL_LOCK = NULL; + + +/** +* This function is similiar to PyErr_Print. It uses the freeswitch print/log mechanism instead of the python sys.stderr +*/ +static void print_python_error(const char * script) +{ + PyObject *pyType = NULL, *pyValue = NULL, *pyTraceback = NULL, *pyString = NULL; + PyObject *pyModule=NULL, *pyFunction = NULL, *pyResult = NULL; + char * buffer = (char*) malloc( 20 * 1024 * sizeof(char)); + /* Variables for the traceback */ + PyTracebackObject * pyTB = NULL/*, *pyTB2 = NULL*/; + char sTemp[256]; + + if (buffer == NULL ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Not enough Memory to create the error buffer"); + } + + /* just for security that we will always have a string terminater */ + memset(buffer, 0, 20 * 1024 * sizeof(char) ); + + /*Get the errordata*/ + PyErr_Fetch(&pyType, &pyValue, &pyTraceback); + PyErr_NormalizeException(&pyType, &pyValue, &pyTraceback); + + + /* Printing header*/ + sprintf(buffer, "Python Error by calling script \"%s\": ", script ); + + if (pyType != NULL && (pyString=PyObject_Str(pyType))!=NULL && (PyString_Check(pyString))) { + strcat(buffer, PyString_AsString(pyString)); + } else { + strcat(buffer, " "); + } + Py_XDECREF(pyString); + + + /*Print error message*/ + if (pyValue != NULL && (pyString=PyObject_Str(pyValue))!=NULL && (PyString_Check(pyString))) { + strcat(buffer, "\nMessage: "); + strcat(buffer, PyString_AsString(pyString)); + } else { + strcat(buffer, "\nMessage: "); + } + Py_XDECREF(pyString); + + + /* Print the traceback */ + if (pyTraceback != NULL && PyTraceBack_Check(pyTraceback)) { + + /*loading traceback module to create the exception data*/ + pyModule = PyImport_ImportModule("traceback"); + if (pyModule) { + strcat(buffer, "\nException: "); + pyFunction = PyObject_GetAttrString(pyModule, "format_exc"); + if (pyFunction) { + pyResult = PyObject_CallObject(pyFunction, NULL); + if (pyResult && PyString_Check(pyResult)) { + strcat(buffer, PyString_AsString(pyResult)); + } else { + strcat(buffer, ""); + } + Py_XDECREF(pyFunction); + + } + Py_XDECREF(pyModule); + + } + + /* Print traceback header */ + strcat(buffer, "\nTraceback (most recent call last)"); + pyTB = (PyTracebackObject*) pyTraceback; + + /* Traceback */ + do { + sprintf((char*)sTemp, "\n\tFile: \"%s\", line %i, in %s", + PyString_AsString(pyTB->tb_frame->f_code->co_filename), + pyTB->tb_lineno, + PyString_AsString(pyTB->tb_frame->f_code->co_name) ); + strcat(buffer, (char*)sTemp); + + pyTB=pyTB->tb_next; + } while(pyTB != NULL); + } + + PyErr_Restore(pyType,pyValue,pyTraceback); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", buffer); + + /* free the resources, we dont need memory leaks here */ + free(buffer); +} + + static void eval_some_python(const char *funcname, char *args, switch_core_session_t *session, switch_stream_handle_t *stream, switch_event_t *params, char **str, struct switch_py_thread *pt) { @@ -131,7 +229,7 @@ static void eval_some_python(const char *funcname, char *args, switch_core_sessi module = PyImport_ImportModule((char *) script); if (!module) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error importing module\n"); - PyErr_Print(); + print_python_error(script); PyErr_Clear(); goto done_swap_out; } @@ -139,7 +237,7 @@ static void eval_some_python(const char *funcname, char *args, switch_core_sessi module = PyImport_ReloadModule(module); if (!module) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error reloading module\n"); - PyErr_Print(); + print_python_error(script); PyErr_Clear(); goto done_swap_out; } @@ -147,7 +245,7 @@ static void eval_some_python(const char *funcname, char *args, switch_core_sessi function = PyObject_GetAttrString(module, (char *) funcname); if (!function) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Module does not define %s\n", funcname); - PyErr_Print(); + print_python_error(script); PyErr_Clear(); goto done_swap_out; } @@ -193,7 +291,7 @@ static void eval_some_python(const char *funcname, char *args, switch_core_sessi } else if (!PyErr_ExceptionMatches(PyExc_SystemExit)) { // Print error, but ignore SystemExit switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error calling python script\n"); - PyErr_Print(); + print_python_error(script); PyErr_Clear(); PyRun_SimpleString("python_makes_sense"); PyGC_Collect(); @@ -310,7 +408,7 @@ static void set_max_recursion_depth(void) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set python recursion limit to %d\n", newMaxRecursionDepth); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set recursion limit to %d\n", newMaxRecursionDepth); - PyErr_Print(); + print_python_error("_freeswitch"); PyErr_Clear(); PyRun_SimpleString("python_makes_sense"); PyGC_Collect(); @@ -403,10 +501,20 @@ SWITCH_STANDARD_API(launch_python) return SWITCH_STATUS_SUCCESS; } + +SWITCH_STANDARD_CHAT_APP(python_chat_function) +{ + eval_some_python("chat", (char *) data, NULL, NULL, message, NULL, NULL); + return SWITCH_STATUS_SUCCESS; + +} + SWITCH_MODULE_LOAD_FUNCTION(mod_python_load) { switch_api_interface_t *api_interface; switch_application_interface_t *app_interface; + switch_chat_application_interface_t *chat_app_interface; + char *pp = getenv("PYTHONPATH"); if (pp) { @@ -454,6 +562,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_python_load) SWITCH_ADD_API(api_interface, "python", "run a python script", api_python, "python "); SWITCH_ADD_APP(app_interface, "python", "Launch python ivr", "Run a python ivr on a channel", python_function, "