asterisk-1.6.1.0/0000755000175000017500000000000011205221755012744 5ustar maniacmaniacasterisk-1.6.1.0/Makefile0000644000175000017500000010136711151056102014404 0ustar maniacmaniac# # Asterisk -- A telephony toolkit for Linux. # # Top level Makefile # # Copyright (C) 1999-2006, Digium, Inc. # # Mark Spencer # # This program is free software, distributed under the terms of # the GNU General Public License # # All Makefiles use the following variables: # # ASTCFLAGS - compiler options # ASTLDFLAGS - linker flags (not libraries) # LIBS - additional libraries, at top-level for all links, # on a single object just for that object # SOLINK - linker flags used only for creating shared objects (.so files), # used for all .so links # # Initial values for ASTCFLAGS and ASTLDFLAGS can be specified in the # environment when running make, as follows: # # $ ASTCFLAGS="-Werror" make ... # # note that this is different from # # $ make ASTCFLAGS="-Werror" ... # # If you need to pass compiler/linker flags as 'make' variables, please use # # $ make COPTS="..." LDOPTS="..." ... # # # You can add the path of local module subdirs from the command line with # make LOCAL_MOD_SUBDIRS= .... export ASTTOPDIR # Top level dir, used in subdirs' Makefiles export ASTERISKVERSION export ASTERISKVERSIONNUM #--- values used for default paths # DESTDIR is the staging (or final) directory where files are copied # during the install process. Define it before 'export', otherwise # export will set it to the empty string making ?= fail. # WARNING: do not put spaces or comments after the value. DESTDIR?=$(INSTALL_PATH) export DESTDIR export INSTALL_PATH # Additional prefix for the following paths export ASTETCDIR # Path for config files export ASTVARRUNDIR export MODULES_DIR export ASTSPOOLDIR export ASTVARLIBDIR export ASTDATADIR export ASTDBDIR export ASTLOGDIR export ASTLIBDIR export ASTMANDIR export ASTHEADERDIR export ASTBINDIR export ASTSBINDIR export AGI_DIR export ASTCONFPATH export OSARCH # Operating system export PROC # Processor type export NOISY_BUILD # Used in Makefile.rules export MENUSELECT_CFLAGS # Options selected in menuselect. export AST_DEVMODE # Set to "yes" for additional compiler # and runtime checks export SOLINK # linker flags for shared objects export STATIC_BUILD # Additional cflags, set to -static # for static builds. Probably # should go directly to ASTLDFLAGS #--- paths to various commands export CC export CXX export AR export RANLIB export HOST_CC export INSTALL export STRIP export DOWNLOAD export AWK export GREP export ID export MD5 # even though we could use '-include makeopts' here, use a wildcard # lookup anyway, so that make won't try to build makeopts if it doesn't # exist (other rules will force it to be built if needed) ifneq ($(wildcard makeopts),) include makeopts endif # Some build systems, such as the one in openwrt, like to pass custom target # CFLAGS and LDFLAGS in the COPTS and LDOPTS variables. ASTCFLAGS+=$(COPTS) ASTLDFLAGS+=$(LDOPTS) #Uncomment this to see all build commands instead of 'quiet' output #NOISY_BUILD=yes empty:= space:=$(empty) $(empty) ASTTOPDIR:=$(subst $(space),\$(space),$(CURDIR)) # Overwite config files on "make samples" OVERWRITE=y # Include debug and macro symbols in the executables (-g) and profiling info (-pg) DEBUG=-g3 # Define standard directories for various platforms # These apply if they are not redefined in asterisk.conf ifeq ($(OSARCH),SunOS) ASTETCDIR=/var/etc/asterisk ASTLIBDIR=/opt/asterisk/lib ASTVARLIBDIR=/var/opt/asterisk ASTDBDIR=$(ASTVARLIBDIR) ASTKEYDIR=$(ASTVARLIBDIR) ASTSPOOLDIR=/var/spool/asterisk ASTLOGDIR=/var/log/asterisk ASTHEADERDIR=/opt/asterisk/include ASTBINDIR=/opt/asterisk/bin ASTSBINDIR=/opt/asterisk/sbin ASTVARRUNDIR=/var/run/asterisk ASTMANDIR=/opt/asterisk/man else ASTETCDIR=$(sysconfdir)/asterisk ASTLIBDIR=$(libdir)/asterisk ASTHEADERDIR=$(includedir)/asterisk ASTBINDIR=$(bindir) ASTSBINDIR=$(sbindir) ASTSPOOLDIR=$(localstatedir)/spool/asterisk ASTLOGDIR=$(localstatedir)/log/asterisk ASTVARRUNDIR=$(localstatedir)/run ASTMANDIR=$(mandir) ifneq ($(findstring BSD,$(OSARCH)),) ASTVARLIBDIR=$(prefix)/share/asterisk ASTVARRUNDIR=$(localstatedir)/run/asterisk ASTDBDIR=$(localstatedir)/db/asterisk else ASTVARLIBDIR=$(localstatedir)/lib/asterisk ASTDBDIR=$(ASTVARLIBDIR) endif ASTKEYDIR=$(ASTVARLIBDIR) endif ifeq ($(ASTDATADIR),) ASTDATADIR:=$(ASTVARLIBDIR) endif # Asterisk.conf is located in ASTETCDIR or by using the -C flag # when starting Asterisk ASTCONFPATH=$(ASTETCDIR)/asterisk.conf MODULES_DIR=$(ASTLIBDIR)/modules AGI_DIR=$(ASTDATADIR)/agi-bin # If you use Apache, you may determine by a grep 'DocumentRoot' of your httpd.conf file HTTP_DOCSDIR=/var/www/html # Determine by a grep 'ScriptAlias' of your Apache httpd.conf file HTTP_CGIDIR=/var/www/cgi-bin # Uncomment this to use the older DSP routines #ASTCFLAGS+=-DOLD_DSP_ROUTINES # If the file .asterisk.makeopts is present in your home directory, you can # include all of your favorite menuselect options so that every time you download # a new version of Asterisk, you don't have to run menuselect to set them. # The file /etc/asterisk.makeopts will also be included but can be overridden # by the file in your home directory. GLOBAL_MAKEOPTS=$(wildcard /etc/asterisk.makeopts) USER_MAKEOPTS=$(wildcard ~/.asterisk.makeopts) MOD_SUBDIR_CFLAGS=-I$(ASTTOPDIR)/include OTHER_SUBDIR_CFLAGS=-I$(ASTTOPDIR)/include # Create OPTIONS variable, but probably we can assign directly to ASTCFLAGS OPTIONS= ifeq ($(OSARCH),linux-gnu) ifeq ($(PROC),x86_64) # You must have GCC 3.4 to use k8, otherwise use athlon PROC=k8 #PROC=athlon endif ifeq ($(PROC),sparc64) #The problem with sparc is the best stuff is in newer versions of gcc (post 3.0) only. #This works for even old (2.96) versions of gcc and provides a small boost either way. #A ultrasparc cpu is really v9 but the stock debian stable 3.0 gcc doesn't support it. #So we go lowest common available by gcc and go a step down, still a step up from #the default as we now have a better instruction set to work with. - Belgarath PROC=ultrasparc OPTIONS+=$(shell if $(CC) -mtune=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-mtune=$(PROC)"; fi) OPTIONS+=$(shell if $(CC) -mcpu=v8 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-mcpu=v8"; fi) OPTIONS+=-fomit-frame-pointer endif ifeq ($(PROC),arm) # The Cirrus logic is the only heavily shipping arm processor with a real floating point unit ifeq ($(SUB_PROC),maverick) OPTIONS+=-fsigned-char -mcpu=ep9312 else ifeq ($(SUB_PROC),xscale) OPTIONS+=-fsigned-char -mcpu=xscale else OPTIONS+=-fsigned-char endif endif endif endif ifeq ($(findstring -save-temps,$(ASTCFLAGS)),) ifeq ($(findstring -pipe,$(ASTCFLAGS)),) ASTCFLAGS+=-pipe endif endif ifeq ($(findstring -Wall,$(ASTCFLAGS)),) ASTCFLAGS+=-Wall endif ASTCFLAGS+=-Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations $(DEBUG) ifeq ($(AST_DEVMODE),yes) ASTCFLAGS+=-Werror ASTCFLAGS+=-Wunused ASTCFLAGS+=$(AST_DECLARATION_AFTER_STATEMENT) ASTCFLAGS+=$(AST_FORTIFY_SOURCE) ASTCFLAGS+=-Wundef ASTCFLAGS+=-Wmissing-format-attribute ASTCFLAGS+=-Wformat=2 endif ifneq ($(findstring BSD,$(OSARCH)),) ASTCFLAGS+=-I/usr/local/include ASTLDFLAGS+=-L/usr/local/lib endif ifeq ($(findstring -march,$(ASTCFLAGS)),) ifneq ($(PROC),ultrasparc) ASTCFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi) endif endif ifeq ($(PROC),ppc) ASTCFLAGS+=-fsigned-char endif ifeq ($(OSARCH),FreeBSD) # -V is understood by BSD Make, not by GNU make. BSDVERSION=$(shell make -V OSVERSION -f /usr/share/mk/bsd.port.subdir.mk) ASTCFLAGS+=$(shell if test $(BSDVERSION) -lt 500016 ; then echo "-D_THREAD_SAFE"; fi) endif ifeq ($(OSARCH),NetBSD) ASTCFLAGS+=-pthread -I/usr/pkg/include endif ifeq ($(OSARCH),OpenBSD) ASTCFLAGS+=-pthread endif ifeq ($(OSARCH),SunOS) ASTCFLAGS+=-Wcast-align -DSOLARIS -I../include/solaris-compat -I/opt/ssl/include -I/usr/local/ssl/include -D_XPG4_2 endif ASTERISKVERSION:=$(shell GREP=$(GREP) AWK=$(AWK) build_tools/make_version .) ifneq ($(wildcard .version),) ASTERISKVERSIONNUM:=$(shell $(AWK) -F. '{printf "%01d%02d%02d", $$1, $$2, $$3}' .version) endif ifneq ($(wildcard .svn),) ASTERISKVERSIONNUM:=999999 endif # XXX MALLOC_DEBUG is probably unused, Makefile.moddir_rules adds the # value directly to ASTCFLAGS ASTCFLAGS+=$(MALLOC_DEBUG)$(OPTIONS) MOD_SUBDIRS:=channels pbx apps codecs formats cdr funcs tests main res $(LOCAL_MOD_SUBDIRS) OTHER_SUBDIRS:=utils agi SUBDIRS:=$(OTHER_SUBDIRS) $(MOD_SUBDIRS) SUBDIRS_INSTALL:=$(SUBDIRS:%=%-install) SUBDIRS_CLEAN:=$(SUBDIRS:%=%-clean) SUBDIRS_DIST_CLEAN:=$(SUBDIRS:%=%-dist-clean) SUBDIRS_UNINSTALL:=$(SUBDIRS:%=%-uninstall) MOD_SUBDIRS_EMBED_LDSCRIPT:=$(MOD_SUBDIRS:%=%-embed-ldscript) MOD_SUBDIRS_EMBED_LDFLAGS:=$(MOD_SUBDIRS:%=%-embed-ldflags) MOD_SUBDIRS_EMBED_LIBS:=$(MOD_SUBDIRS:%=%-embed-libs) MOD_SUBDIRS_MENUSELECT_TREE:=$(MOD_SUBDIRS:%=%-menuselect-tree) ifneq ($(findstring darwin,$(OSARCH)),) ASTCFLAGS+=-D__Darwin__ SOLINK=-dynamic -bundle -undefined suppress -force_flat_namespace else # These are used for all but Darwin SOLINK=-shared ifneq ($(findstring BSD,$(OSARCH)),) LDFLAGS+=-L/usr/local/lib endif endif ifeq ($(OSARCH),SunOS) SOLINK=-shared -fpic -L/usr/local/ssl/lib -lrt endif # comment to print directories during submakes #PRINT_DIR=yes SILENTMAKE:=$(MAKE) --quiet --no-print-directory ifneq ($(PRINT_DIR)$(NOISY_BUILD),) SUBMAKE:=$(MAKE) else SUBMAKE:=$(MAKE) --quiet --no-print-directory endif # This is used when generating the doxygen documentation ifneq ($(DOT),:) HAVEDOT=yes else HAVEDOT=no endif # $(MAKE) is printed in several places, and we want it to be a # fixed size string. Define a variable whose name has also the # same size, so we can easily align text. ifeq ($(MAKE), gmake) mK="gmake" else mK=" make" endif all: _all @echo " +--------- Asterisk Build Complete ---------+" @echo " + Asterisk has successfully been built, and +" @echo " + can be installed by running: +" @echo " + +" @echo " + $(mK) install +" @echo " +-------------------------------------------+" _all: cleantest makeopts $(SUBDIRS) makeopts: configure @echo "****" @echo "**** The configure script must be executed before running '$(MAKE)'." @echo "**** Please run \"./configure\"." @echo "****" @exit 1 menuselect.makeopts: menuselect/menuselect menuselect-tree makeopts menuselect/menuselect --check-deps menuselect.makeopts $(GLOBAL_MAKEOPTS) $(USER_MAKEOPTS) $(MOD_SUBDIRS_EMBED_LDSCRIPT): @echo "EMBED_LDSCRIPTS+="`$(SILENTMAKE) -C $(@:-embed-ldscript=) SUBDIR=$(@:-embed-ldscript=) __embed_ldscript` >> makeopts.embed_rules $(MOD_SUBDIRS_EMBED_LDFLAGS): @echo "EMBED_LDFLAGS+="`$(SILENTMAKE) -C $(@:-embed-ldflags=) SUBDIR=$(@:-embed-ldflags=) __embed_ldflags` >> makeopts.embed_rules $(MOD_SUBDIRS_EMBED_LIBS): @echo "EMBED_LIBS+="`$(SILENTMAKE) -C $(@:-embed-libs=) SUBDIR=$(@:-embed-libs=) __embed_libs` >> makeopts.embed_rules $(MOD_SUBDIRS_MENUSELECT_TREE): @$(SUBMAKE) -C $(@:-menuselect-tree=) SUBDIR=$(@:-menuselect-tree=) moduleinfo @$(SUBMAKE) -C $(@:-menuselect-tree=) SUBDIR=$(@:-menuselect-tree=) makeopts makeopts.embed_rules: menuselect.makeopts @echo "Generating embedded module rules ..." @rm -f $@ @$(SUBMAKE) $(MOD_SUBDIRS_EMBED_LDSCRIPT) @$(SUBMAKE) $(MOD_SUBDIRS_EMBED_LDFLAGS) @$(SUBMAKE) $(MOD_SUBDIRS_EMBED_LIBS) $(SUBDIRS): main/version.c include/asterisk/version.h include/asterisk/build.h include/asterisk/buildopts.h defaults.h makeopts.embed_rules ifeq ($(findstring $(OSARCH), mingw32 cygwin ),) # Non-windows: # ensure that all module subdirectories are processed before 'main' during # a parallel build, since if there are modules selected to be embedded the # directories containing them must be completed before the main Asterisk # binary can be built main: $(filter-out main,$(MOD_SUBDIRS)) else # Windows: we need to build main (i.e. the asterisk dll) first, # followed by res, followed by the other directories, because # dll symbols must be resolved during linking and not at runtime. D1:= $(filter-out main,$(MOD_SUBDIRS)) D1:= $(filter-out res,$(D1)) $(D1): res res: main endif $(MOD_SUBDIRS): @ASTCFLAGS="$(MOD_SUBDIR_CFLAGS) $(ASTCFLAGS)" ASTLDFLAGS="$(ASTLDFLAGS)" $(SUBMAKE) --no-builtin-rules -C $@ SUBDIR=$@ all $(OTHER_SUBDIRS): @ASTCFLAGS="$(OTHER_SUBDIR_CFLAGS) $(ASTCFLAGS)" ASTLDFLAGS="$(ASTLDFLAGS)" $(SUBMAKE) --no-builtin-rules -C $@ SUBDIR=$@ all defaults.h: makeopts @build_tools/make_defaults_h > $@.tmp @cmp -s $@.tmp $@ || mv $@.tmp $@ @rm -f $@.tmp main/version.c: FORCE @build_tools/make_version_c > $@.tmp @cmp -s $@.tmp $@ || mv $@.tmp $@ @rm -f $@.tmp include/asterisk/version.h: FORCE @build_tools/make_version_h > $@.tmp @cmp -s $@.tmp $@ || mv $@.tmp $@ @rm -f $@.tmp include/asterisk/buildopts.h: menuselect.makeopts @build_tools/make_buildopts_h > $@.tmp @cmp -s $@.tmp $@ || mv $@.tmp $@ @rm -f $@.tmp include/asterisk/build.h: @build_tools/make_build_h > $@.tmp @cmp -s $@.tmp $@ || mv $@.tmp $@ @rm -f $@.tmp $(SUBDIRS_CLEAN): @$(SUBMAKE) -C $(@:-clean=) clean $(SUBDIRS_DIST_CLEAN): @$(SUBMAKE) -C $(@:-dist-clean=) dist-clean clean: $(SUBDIRS_CLEAN) _clean _clean: rm -f defaults.h rm -f include/asterisk/build.h rm -f main/version.c rm -f include/asterisk/version.h @$(MAKE) -C menuselect clean cp -f .cleancount .lastclean dist-clean: distclean distclean: $(SUBDIRS_DIST_CLEAN) _clean @$(MAKE) -C menuselect dist-clean @$(MAKE) -C sounds dist-clean rm -f menuselect.makeopts makeopts menuselect-tree menuselect.makedeps rm -f makeopts.embed_rules rm -f config.log config.status config.cache rm -rf autom4te.cache rm -f include/asterisk/autoconfig.h rm -f include/asterisk/buildopts.h rm -rf doc/api rm -f build_tools/menuselect-deps datafiles: _all if [ x`$(ID) -un` = xroot ]; then CFLAGS="$(ASTCFLAGS)" sh build_tools/mkpkgconfig $(DESTDIR)/usr/lib/pkgconfig; fi # Should static HTTP be installed during make samples or even with its own target ala # webvoicemail? There are portions here that *could* be customized but might also be # improved a lot. I'll put it here for now. mkdir -p $(DESTDIR)$(ASTDATADIR)/static-http for x in static-http/*; do \ $(INSTALL) -m 644 $$x $(DESTDIR)$(ASTDATADIR)/static-http ; \ done if [ -d doc/tex/asterisk ] ; then \ mkdir -p $(DESTDIR)$(ASTDATADIR)/static-http/docs ; \ for n in doc/tex/asterisk/* ; do \ $(INSTALL) -m 644 $$n $(DESTDIR)$(ASTDATADIR)/static-http/docs ; \ done \ fi mkdir -p $(DESTDIR)$(ASTDATADIR)/images for x in images/*.jpg; do \ $(INSTALL) -m 644 $$x $(DESTDIR)$(ASTDATADIR)/images ; \ done mkdir -p $(DESTDIR)$(AGI_DIR) $(MAKE) -C sounds install update: @if [ -d .svn ]; then \ echo "Updating from Subversion..." ; \ fromrev="`svn info | $(AWK) '/Revision: / {print $$2}'`"; \ svn update | tee update.out; \ torev="`svn info | $(AWK) '/Revision: / {print $$2}'`"; \ echo "`date` Updated from revision $${fromrev} to $${torev}." >> update.log; \ rm -f .version; \ if [ `grep -c ^C update.out` -gt 0 ]; then \ echo ; echo "The following files have conflicts:" ; \ grep ^C update.out | cut -b4- ; \ fi ; \ rm -f update.out; \ else \ echo "Not under version control"; \ fi NEWHEADERS=$(notdir $(wildcard include/asterisk/*.h)) OLDHEADERS=$(filter-out $(NEWHEADERS),$(notdir $(wildcard $(DESTDIR)$(ASTHEADERDIR)/*.h))) installdirs: mkdir -p $(DESTDIR)$(MODULES_DIR) mkdir -p $(DESTDIR)$(ASTSBINDIR) mkdir -p $(DESTDIR)$(ASTETCDIR) mkdir -p $(DESTDIR)$(ASTBINDIR) mkdir -p $(DESTDIR)$(ASTVARRUNDIR) mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/voicemail mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/dictate mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/system mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/tmp mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/meetme mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/monitor bininstall: _all installdirs $(SUBDIRS_INSTALL) $(INSTALL) -m 755 main/asterisk $(DESTDIR)$(ASTSBINDIR)/ $(LN) -sf asterisk $(DESTDIR)$(ASTSBINDIR)/rasterisk $(INSTALL) -m 755 contrib/scripts/astgenkey $(DESTDIR)$(ASTSBINDIR)/ $(INSTALL) -m 755 contrib/scripts/autosupport $(DESTDIR)$(ASTSBINDIR)/ if [ ! -f $(DESTDIR)$(ASTSBINDIR)/safe_asterisk ]; then \ cat contrib/scripts/safe_asterisk | sed 's|__ASTERISK_SBIN_DIR__|$(ASTSBINDIR)|;s|__ASTERISK_VARRUN_DIR__|$(ASTVARRUNDIR)|;' > $(DESTDIR)$(ASTSBINDIR)/safe_asterisk ;\ chmod 755 $(DESTDIR)$(ASTSBINDIR)/safe_asterisk;\ fi $(INSTALL) -d $(DESTDIR)$(ASTHEADERDIR) $(INSTALL) -m 644 include/asterisk.h $(DESTDIR)$(includedir) $(INSTALL) -m 644 include/asterisk/*.h $(DESTDIR)$(ASTHEADERDIR) if [ -n "$(OLDHEADERS)" ]; then \ rm -f $(addprefix $(DESTDIR)$(ASTHEADERDIR)/,$(OLDHEADERS)) ;\ fi mkdir -p $(DESTDIR)$(ASTLOGDIR)/cdr-csv mkdir -p $(DESTDIR)$(ASTLOGDIR)/cdr-custom mkdir -p $(DESTDIR)$(ASTDATADIR)/keys mkdir -p $(DESTDIR)$(ASTDATADIR)/firmware mkdir -p $(DESTDIR)$(ASTDATADIR)/firmware/iax mkdir -p $(DESTDIR)$(ASTMANDIR)/man8 $(INSTALL) -m 644 keys/iaxtel.pub $(DESTDIR)$(ASTDATADIR)/keys $(INSTALL) -m 644 keys/freeworlddialup.pub $(DESTDIR)$(ASTDATADIR)/keys $(INSTALL) -m 644 doc/asterisk.8 $(DESTDIR)$(ASTMANDIR)/man8 $(INSTALL) -m 644 contrib/scripts/astgenkey.8 $(DESTDIR)$(ASTMANDIR)/man8 $(INSTALL) -m 644 contrib/scripts/autosupport.8 $(DESTDIR)$(ASTMANDIR)/man8 $(INSTALL) -m 644 contrib/scripts/safe_asterisk.8 $(DESTDIR)$(ASTMANDIR)/man8 if [ -f contrib/firmware/iax/iaxy.bin ] ; then \ $(INSTALL) -m 644 contrib/firmware/iax/iaxy.bin $(DESTDIR)$(ASTDATADIR)/firmware/iax/iaxy.bin; \ fi $(SUBDIRS_INSTALL): @DESTDIR="$(DESTDIR)" ASTSBINDIR="$(ASTSBINDIR)" $(SUBMAKE) -C $(@:-install=) install NEWMODS:=$(foreach d,$(MOD_SUBDIRS),$(notdir $(wildcard $(d)/*.so))) OLDMODS=$(filter-out $(NEWMODS),$(notdir $(wildcard $(DESTDIR)$(MODULES_DIR)/*.so))) oldmodcheck: @if [ -n "$(OLDMODS)" ]; then \ echo " WARNING WARNING WARNING" ;\ echo "" ;\ echo " Your Asterisk modules directory, located at" ;\ echo " $(DESTDIR)$(MODULES_DIR)" ;\ echo " contains modules that were not installed by this " ;\ echo " version of Asterisk. Please ensure that these" ;\ echo " modules are compatible with this version before" ;\ echo " attempting to run Asterisk." ;\ echo "" ;\ for f in $(OLDMODS); do \ echo " $$f" ;\ done ;\ echo "" ;\ echo " WARNING WARNING WARNING" ;\ fi badshell: ifneq ($(findstring ~,$(DESTDIR)),) @echo "Your shell doesn't do ~ expansion when expected (specifically, when doing \"make install DESTDIR=~/path\")." @echo "Try replacing ~ with \$$HOME, as in \"make install DESTDIR=\$$HOME/path\"." @exit 1 endif install: badshell datafiles bininstall @if [ -x /usr/sbin/asterisk-post-install ]; then \ /usr/sbin/asterisk-post-install $(DESTDIR) . ; \ fi @echo " +---- Asterisk Installation Complete -------+" @echo " + +" @echo " + YOU MUST READ THE SECURITY DOCUMENT +" @echo " + +" @echo " + Asterisk has successfully been installed. +" @echo " + If you would like to install the sample +" @echo " + configuration files (overwriting any +" @echo " + existing config files), run: +" @echo " + +" @echo " + $(mK) samples +" @echo " + +" @echo " +----------------- or ---------------------+" @echo " + +" @echo " + You can go ahead and install the asterisk +" @echo " + program documentation now or later run: +" @echo " + +" @echo " + $(mK) progdocs +" @echo " + +" @echo " + **Note** This requires that you have +" @echo " + doxygen installed on your local system +" @echo " +-------------------------------------------+" @$(MAKE) -s oldmodcheck upgrade: bininstall # XXX why *.adsi is installed first ? adsi: @echo Installing adsi config files... @mkdir -p $(DESTDIR)$(ASTETCDIR) @for x in configs/*.adsi; do \ dst="$(DESTDIR)$(ASTETCDIR)/`$(BASENAME) $$x`" ; \ if [ -f $${dst} ] ; then \ echo "Overwriting $$x" ; \ else \ echo "Installing $$x" ; \ fi ; \ $(INSTALL) -m 644 $$x $(DESTDIR)$(ASTETCDIR)/`$(BASENAME) $$x` ; \ done samples: adsi @echo Installing other config files... @mkdir -p $(DESTDIR)$(ASTETCDIR) @for x in configs/*.sample; do \ dst="$(DESTDIR)$(ASTETCDIR)/`$(BASENAME) $$x .sample`" ; \ if [ -f $${dst} ]; then \ if [ "$(OVERWRITE)" = "y" ]; then \ if cmp -s $${dst} $$x ; then \ echo "Config file $$x is unchanged"; \ continue; \ fi ; \ mv -f $${dst} $${dst}.old ; \ else \ echo "Skipping config file $$x"; \ continue; \ fi ;\ fi ; \ echo "Installing file $$x"; \ $(INSTALL) -m 644 $$x $${dst} ;\ done @if [ "$(OVERWRITE)" = "y" ] || [ ! -f $(DESTDIR)$(ASTCONFPATH) ]; then \ echo "Creating asterisk.conf"; \ ( \ echo "[directories](!) ; remove the (!) to enable this" ; \ echo "astetcdir => $(ASTETCDIR)" ; \ echo "astmoddir => $(MODULES_DIR)" ; \ echo "astvarlibdir => $(ASTVARLIBDIR)" ; \ echo "astdbdir => $(ASTDBDIR)" ; \ echo "astkeydir => $(ASTKEYDIR)" ; \ echo "astdatadir => $(ASTDATADIR)" ; \ echo "astagidir => $(AGI_DIR)" ; \ echo "astspooldir => $(ASTSPOOLDIR)" ; \ echo "astrundir => $(ASTVARRUNDIR)" ; \ echo "astlogdir => $(ASTLOGDIR)" ; \ echo "" ; \ echo ";[options]" ; \ echo ";verbose = 3" ; \ echo ";debug = 3" ; \ echo ";alwaysfork = yes ; same as -F at startup" ; \ echo ";nofork = yes ; same as -f at startup" ; \ echo ";quiet = yes ; same as -q at startup" ; \ echo ";timestamp = yes ; same as -T at startup" ; \ echo ";execincludes = yes ; support #exec in config files" ; \ echo ";console = yes ; Run as console (same as -c at startup)" ; \ echo ";highpriority = yes ; Run realtime priority (same as -p at startup)" ; \ echo ";initcrypto = yes ; Initialize crypto keys (same as -i at startup)" ; \ echo ";nocolor = yes ; Disable console colors" ; \ echo ";dontwarn = yes ; Disable some warnings" ; \ echo ";dumpcore = yes ; Dump core on crash (same as -g at startup)" ; \ echo ";languageprefix = yes ; Use the new sound prefix path syntax" ; \ echo ";internal_timing = yes" ; \ echo ";systemname = my_system_name ; prefix uniqueid with a system name for global uniqueness issues" ; \ echo ";autosystemname = yes ; automatically set systemname to hostname - uses 'localhost' on failure, or systemname if set" ; \ echo ";maxcalls = 10 ; Maximum amount of calls allowed" ; \ echo ";maxload = 0.9 ; Asterisk stops accepting new calls if the load average exceed this limit" ; \ echo ";maxfiles = 1000 ; Maximum amount of openfiles" ; \ echo ";minmemfree = 1 ; in MBs, Asterisk stops accepting new calls if the amount of free memory falls below this watermark" ; \ echo ";cache_record_files = yes ; Cache recorded sound files to another directory during recording" ; \ echo ";record_cache_dir = /tmp ; Specify cache directory (used in cnjunction with cache_record_files)" ; \ echo ";transmit_silence_during_record = yes ; Transmit SLINEAR silence while a channel is being recorded" ; \ echo ";transmit_silence = yes ; Transmit SLINEAR silence while a channel is being recorded or DTMF is being generated" ; \ echo ";transcode_via_sln = yes ; Build transcode paths via SLINEAR, instead of directly" ; \ echo ";runuser = asterisk ; The user to run as" ; \ echo ";rungroup = asterisk ; The group to run as" ; \ echo "" ; \ echo "; Changing the following lines may compromise your security." ; \ echo ";[files]" ; \ echo ";astctlpermissions = 0660" ; \ echo ";astctlowner = root" ; \ echo ";astctlgroup = apache" ; \ echo ";astctl = asterisk.ctl" ; \ echo "" ; \ echo "[compat]" ; \ echo "pbx_realtime=1.6" ; \ echo "res_agi=1.6" ; \ echo "app_set=1.6" ; \ ) > $(DESTDIR)$(ASTCONFPATH) ; \ else \ echo "Skipping asterisk.conf creation"; \ fi mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/INBOX build_tools/make_sample_voicemail $(DESTDIR)/$(ASTDATADIR) $(DESTDIR)/$(ASTSPOOLDIR) @mkdir -p $(DESTDIR)$(ASTDATADIR)/phoneprov @for x in phoneprov/*; do \ dst="$(DESTDIR)$(ASTDATADIR)/$$x" ; \ if [ -f $${dst} ]; then \ if [ "$(OVERWRITE)" = "y" ]; then \ if cmp -s $${dst} $$x ; then \ echo "Config file $$x is unchanged"; \ continue; \ fi ; \ mv -f $${dst} $${dst}.old ; \ else \ echo "Skipping config file $$x"; \ continue; \ fi ;\ fi ; \ echo "Installing file $$x"; \ $(INSTALL) -m 644 $$x $${dst} ;\ done webvmail: @[ -d $(DESTDIR)$(HTTP_DOCSDIR)/ ] || ( printf "http docs directory not found.\nUpdate assignment of variable HTTP_DOCSDIR in Makefile!\n" && exit 1 ) @[ -d $(DESTDIR)$(HTTP_CGIDIR) ] || ( printf "cgi-bin directory not found.\nUpdate assignment of variable HTTP_CGIDIR in Makefile!\n" && exit 1 ) $(INSTALL) -m 4755 -o root -g root contrib/scripts/vmail.cgi $(DESTDIR)$(HTTP_CGIDIR)/vmail.cgi mkdir -p $(DESTDIR)$(HTTP_DOCSDIR)/_asterisk for x in images/*.gif; do \ $(INSTALL) -m 644 $$x $(DESTDIR)$(HTTP_DOCSDIR)/_asterisk/; \ done @echo " +--------- Asterisk Web Voicemail ----------+" @echo " + +" @echo " + Asterisk Web Voicemail is installed in +" @echo " + your cgi-bin directory: +" @echo " + $(DESTDIR)$(HTTP_CGIDIR)" @echo " + IT USES A SETUID ROOT PERL SCRIPT, SO +" @echo " + IF YOU DON'T LIKE THAT, UNINSTALL IT! +" @echo " + +" @echo " + Other static items have been stored in: +" @echo " + $(DESTDIR)$(HTTP_DOCSDIR)" @echo " + +" @echo " + If these paths do not match your httpd +" @echo " + installation, correct the definitions +" @echo " + in your Makefile of HTTP_CGIDIR and +" @echo " + HTTP_DOCSDIR +" @echo " + +" @echo " +-------------------------------------------+" progdocs: (cat contrib/asterisk-ng-doxygen; echo "HAVE_DOT=$(HAVEDOT)"; \ echo "PROJECT_NUMBER=$(ASTERISKVERSION)") | doxygen - install-logrotate: if [ ! -d $(ASTETCDIR)/../logrotate.d ]; then \ mkdir $(ASTETCDIR)/../logrotate.d ; \ fi sed 's#__LOGDIR__#$(ASTLOGDIR)#g' < contrib/scripts/asterisk.logrotate | sed 's#__SBINDIR__#$(ASTSBINDIR)#g' > contrib/scripts/asterisk.logrotate.tmp install -m 0644 contrib/scripts/asterisk.logrotate.tmp $(ASTETCDIR)/../logrotate.d/asterisk rm -f contrib/scripts/asterisk.logrotate.tmp config: @if [ "${OSARCH}" = "linux-gnu" ]; then \ if [ -f /etc/redhat-release -o -f /etc/fedora-release ]; then \ $(INSTALL) -m 755 contrib/init.d/rc.redhat.asterisk $(DESTDIR)/etc/rc.d/init.d/asterisk; \ if [ -z "$(DESTDIR)" ]; then /sbin/chkconfig --add asterisk; fi; \ elif [ -f /etc/debian_version ]; then \ $(INSTALL) -m 755 contrib/init.d/rc.debian.asterisk $(DESTDIR)/etc/init.d/asterisk; \ if [ -z "$(DESTDIR)" ]; then /usr/sbin/update-rc.d asterisk start 50 2 3 4 5 . stop 91 2 3 4 5 .; fi; \ elif [ -f /etc/gentoo-release ]; then \ $(INSTALL) -m 755 contrib/init.d/rc.gentoo.asterisk $(DESTDIR)/etc/init.d/asterisk; \ if [ -z "$(DESTDIR)" ]; then /sbin/rc-update add asterisk default; fi; \ elif [ -f /etc/mandrake-release -o -f /etc/mandriva-release ]; then \ $(INSTALL) -m 755 contrib/init.d/rc.mandriva.asterisk $(DESTDIR)/etc/rc.d/init.d/asterisk; \ if [ -z "$(DESTDIR)" ]; then /sbin/chkconfig --add asterisk; fi; \ elif [ -f /etc/SuSE-release -o -f /etc/novell-release ]; then \ $(INSTALL) -m 755 contrib/init.d/rc.suse.asterisk $(DESTDIR)/etc/init.d/asterisk; \ if [ -z "$(DESTDIR)" ]; then /sbin/chkconfig --add asterisk; fi; \ elif [ -f /etc/slackware-version ]; then \ echo "Slackware is not currently supported, although an init script does exist for it." \ else \ echo "We could not install init scripts for your distribution."; \ fi \ else \ echo "We could not install init scripts for your operating system."; \ fi sounds: $(MAKE) -C sounds all # If the cleancount has been changed, force a make clean. # .cleancount is the global clean count, and .lastclean is the # last clean count we had cleantest: @cmp -s .cleancount .lastclean || $(MAKE) clean $(SUBDIRS_UNINSTALL): @$(SUBMAKE) -C $(@:-uninstall=) uninstall _uninstall: $(SUBDIRS_UNINSTALL) rm -f $(DESTDIR)$(MODULES_DIR)/* rm -f $(DESTDIR)$(ASTSBINDIR)/*asterisk* rm -f $(DESTDIR)$(ASTSBINDIR)/astgenkey rm -f $(DESTDIR)$(ASTSBINDIR)/autosupport rm -rf $(DESTDIR)$(ASTHEADERDIR) rm -rf $(DESTDIR)$(ASTDATADIR)/firmware rm -f $(DESTDIR)$(ASTMANDIR)/man8/asterisk.8 rm -f $(DESTDIR)$(ASTMANDIR)/man8/astgenkey.8 rm -f $(DESTDIR)$(ASTMANDIR)/man8/autosupport.8 rm -f $(DESTDIR)$(ASTMANDIR)/man8/safe_asterisk.8 $(MAKE) -C sounds uninstall uninstall: _uninstall @echo " +--------- Asterisk Uninstall Complete -----+" @echo " + Asterisk binaries, sounds, man pages, +" @echo " + headers, modules, and firmware builds, +" @echo " + have all been uninstalled. +" @echo " + +" @echo " + To remove ALL traces of Asterisk, +" @echo " + including configuration, spool +" @echo " + directories, and logs, run the following +" @echo " + command: +" @echo " + +" @echo " + $(mK) uninstall-all +" @echo " +-------------------------------------------+" uninstall-all: _uninstall rm -rf $(DESTDIR)$(ASTLIBDIR) rm -rf $(DESTDIR)$(ASTVARLIBDIR) rm -rf $(DESTDIR)$(ASTDATADIR) rm -rf $(DESTDIR)$(ASTSPOOLDIR) rm -rf $(DESTDIR)$(ASTETCDIR) rm -rf $(DESTDIR)$(ASTLOGDIR) menuconfig: menuselect cmenuconfig: cmenuselect gmenuconfig: gmenuselect nmenuconfig: nmenuselect menuselect: menuselect/cmenuselect menuselect/nmenuselect menuselect/gmenuselect @if [ -x menuselect/nmenuselect ]; then \ $(MAKE) nmenuselect; \ elif [ -x menuselect/cmenuselect ]; then \ $(MAKE) cmenuselect; \ elif [ -x menuselect/gmenuselect ]; then \ $(MAKE) gmenuselect; \ else \ echo "No menuselect user interface found. Install ncurses,"; \ echo "newt or GTK libraries to build one and re-rerun"; \ echo "'make menuselect'."; \ fi cmenuselect: menuselect/cmenuselect menuselect-tree -@menuselect/cmenuselect menuselect.makeopts $(GLOBAL_MAKEOPTS) $(USER_MAKEOPTS) && (echo "menuselect changes saved!"; rm -f channels/h323/Makefile.ast main/asterisk) || echo "menuselect changes NOT saved!" gmenuselect: menuselect/gmenuselect menuselect-tree -@menuselect/gmenuselect menuselect.makeopts $(GLOBAL_MAKEOPTS) $(USER_MAKEOPTS) && (echo "menuselect changes saved!"; rm -f channels/h323/Makefile.ast main/asterisk) || echo "menuselect changes NOT saved!" nmenuselect: menuselect/nmenuselect menuselect-tree -@menuselect/nmenuselect menuselect.makeopts $(GLOBAL_MAKEOPTS) $(USER_MAKEOPTS) && (echo "menuselect changes saved!"; rm -f channels/h323/Makefile.ast main/asterisk) || echo "menuselect changes NOT saved!" # options for make in menuselect/ MAKE_MENUSELECT=CC="$(HOST_CC)" CXX="$(CXX)" LD="" AR="" RANLIB="" CFLAGS="" $(MAKE) -C menuselect CONFIGURE_SILENT="--silent" menuselect/menuselect: menuselect/makeopts $(MAKE_MENUSELECT) menuselect menuselect/cmenuselect: menuselect/makeopts $(MAKE_MENUSELECT) cmenuselect menuselect/gmenuselect: menuselect/makeopts $(MAKE_MENUSELECT) gmenuselect menuselect/nmenuselect: menuselect/makeopts $(MAKE_MENUSELECT) nmenuselect menuselect/makeopts: makeopts $(MAKE_MENUSELECT) makeopts menuselect-tree: $(foreach dir,$(filter-out main,$(MOD_SUBDIRS)),$(wildcard $(dir)/*.c) $(wildcard $(dir)/*.cc)) build_tools/cflags.xml build_tools/cflags-devmode.xml sounds/sounds.xml build_tools/embed_modules.xml configure @echo "Generating input for menuselect ..." @echo "" > $@ @echo >> $@ @echo "" >> $@ @for dir in $(sort $(filter-out main,$(MOD_SUBDIRS))); do $(SILENTMAKE) -C $${dir} SUBDIR=$${dir} moduleinfo >> $@; done @cat build_tools/cflags.xml >> $@ @for dir in $(sort $(filter-out main,$(MOD_SUBDIRS))); do $(SILENTMAKE) -C $${dir} SUBDIR=$${dir} makeopts >> $@; done @if [ "${AST_DEVMODE}" = "yes" ]; then \ cat build_tools/cflags-devmode.xml >> $@; \ fi @cat build_tools/embed_modules.xml >> $@ @cat sounds/sounds.xml >> $@ @echo "" >> $@ pdf: asterisk.pdf asterisk.pdf: $(MAKE) -C doc/tex asterisk.pdf .PHONY: menuselect menuselect.makeopts main sounds clean dist-clean distclean all prereqs cleantest uninstall _uninstall uninstall-all pdf dont-optimize $(SUBDIRS_INSTALL) $(SUBDIRS_DIST_CLEAN) $(SUBDIRS_CLEAN) $(SUBDIRS_UNINSTALL) $(SUBDIRS) $(MOD_SUBDIRS_EMBED_LDSCRIPT) $(MOD_SUBDIRS_EMBED_LDFLAGS) $(MOD_SUBDIRS_EMBED_LIBS) badshell installdirs _clean FORCE: asterisk-1.6.1.0/pbx/0000755000175000017500000000000011205221755013535 5ustar maniacmaniacasterisk-1.6.1.0/pbx/Makefile0000644000175000017500000000137511111125371015174 0ustar maniacmaniac# # Asterisk -- A telephony toolkit for Linux. # # Makefile for PBX modules # # Copyright (C) 1999-2006, Digium, Inc. # # This program is free software, distributed under the terms of # the GNU General Public License # -include $(ASTTOPDIR)/menuselect.makeopts $(ASTTOPDIR)/menuselect.makedeps MODULE_PREFIX=pbx MENUSELECT_CATEGORY=PBX MENUSELECT_DESCRIPTION=PBX Modules all: _all include $(ASTTOPDIR)/Makefile.moddir_rules ifneq ($(findstring $(OSARCH), mingw32 cygwin ),) LIBS+= -lres_ael_share.so -lres_monitor.so endif clean:: rm -f ael/*.o ael/*.i dundi-parser.o: dundi-parser.h dundi-parser.o: ASTCFLAGS+=-I. pbx_gtkconsole.o: ASTCFLAGS+=-Wno-strict-prototypes $(if $(filter pbx_dundi,$(EMBEDDED_MODS)),modules.link,pbx_dundi.so): dundi-parser.o asterisk-1.6.1.0/pbx/pbx_gtkconsole.c0000644000175000017500000003247011031733021016717 0ustar maniacmaniac/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 1999 - 2005, Digium, Inc. * * Mark Spencer * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. */ /*! \file * * \brief GTK Console monitor -- very kludgy right now * */ /*** MODULEINFO gtk no ***/ #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision: 126356 $") #include #include #include #include #include #include "asterisk/pbx.h" #include "asterisk/config.h" #include "asterisk/module.h" #include "asterisk/logger.h" #include "asterisk/cli.h" #include "asterisk/utils.h" #include "asterisk/paths.h" #include "asterisk/term.h" AST_MUTEX_DEFINE_STATIC(verb_lock); static pthread_t console_thread; static int inuse=0; static int clipipe[2]; static int cleanupid = -1; static GtkWidget *window; static GtkWidget *quit; static GtkWidget *closew; static GtkWidget *verb; static GtkWidget *modules; static GtkWidget *statusbar; static GtkWidget *cli; static struct timeval last; static void update_statusbar(char *msg) { gtk_statusbar_pop(GTK_STATUSBAR(statusbar), 1); gtk_statusbar_push(GTK_STATUSBAR(statusbar), 1, msg); } static int unload_module(void) { if (inuse) { /* Kill off the main thread */ pthread_cancel(console_thread); gdk_threads_enter(); gtk_widget_destroy(window); gdk_threads_leave(); close(clipipe[0]); close(clipipe[1]); } return 0; } static int cleanup(void *useless) { gdk_threads_enter(); gtk_clist_thaw(GTK_CLIST(verb)); gtk_widget_queue_resize(verb->parent); gtk_clist_moveto(GTK_CLIST(verb), GTK_CLIST(verb)->rows - 1, 0, 0, 0); cleanupid = -1; gdk_threads_leave(); return 0; } static void __verboser(const char *_stuff) { char *s2[2]; struct timeval tv; int ms; char *stuff; stuff = ast_strdupa(_stuff); term_strip(stuff, stuff, strlen(stuff) + 1); s2[0] = (char *)stuff; s2[1] = NULL; gtk_clist_freeze(GTK_CLIST(verb)); gtk_clist_append(GTK_CLIST(verb), s2); if (!ast_tvzero(last)) { gdk_threads_leave(); gettimeofday(&tv, NULL); if (cleanupid > -1) gtk_timeout_remove(cleanupid); ms = ast_tvdiff_ms(tv, last); if (ms < 100) { /* We just got a message within 100ms, so just schedule an update in the near future */ cleanupid = gtk_timeout_add(200, cleanup, NULL); } else { cleanup(&cleanupid); } last = tv; } else { gettimeofday(&last, NULL); } } static void verboser(const char *stuff) { if (*stuff == 127) { stuff++; } ast_mutex_lock(&verb_lock); /* Lock appropriately if we're really being called in verbose mode */ __verboser(stuff); ast_mutex_unlock(&verb_lock); } static void cliinput(void *data, int source, GdkInputCondition ic) { static char buf[256]; static int offset = 0; int res; char *c; char *l; char n; /* Read as much stuff is there */ res = read(source, buf + offset, sizeof(buf) - 1 - offset); if (res > -1) buf[res + offset] = '\0'; /* make sure we've null terminated whatever we have so far */ c = buf; l = buf; while(*c) { if (*c == '\n') { /* Keep the trailing \n */ c++; n = *c; *c = '\0'; __verboser(l); *(c - 1) = '\0'; *c = n; l = c; } else c++; } if (strlen(l)) { /* We have some left over */ memmove(buf, l, strlen(l) + 1); offset = strlen(buf); } else { offset = 0; } } static void remove_module(void) { int res; char *module; char buf[256]; if (GTK_CLIST(modules)->selection) { module = (char *) gtk_clist_get_row_data(GTK_CLIST(modules), (long) GTK_CLIST(modules)->selection->data); gdk_threads_leave(); res = ast_unload_resource(module, 0); gdk_threads_enter(); if (res) { snprintf(buf, sizeof(buf), "Module '%s' is in use", module); update_statusbar(buf); } else { snprintf(buf, sizeof(buf), "Module '%s' removed", module); update_statusbar(buf); } } } static int reload(void) { int res, x; char *module; char buf[256]; if (GTK_CLIST(modules)->selection) { module= (char *)gtk_clist_get_row_data(GTK_CLIST(modules), (long) GTK_CLIST(modules)->selection->data); module = strdup(module); if (module) { gdk_threads_leave(); res = ast_unload_resource(module, 0); gdk_threads_enter(); if (res) { snprintf(buf, sizeof(buf), "Module '%s' is in use", module); update_statusbar(buf); } else { gdk_threads_leave(); res = ast_load_resource(module); gdk_threads_enter(); if (res) { snprintf(buf, sizeof(buf), "Error reloading module '%s'", module); } else { snprintf(buf, sizeof(buf), "Module '%s' reloaded", module); } for (x=0; x < GTK_CLIST(modules)->rows; x++) { if (!strcmp((char *)gtk_clist_get_row_data(GTK_CLIST(modules), x), module)) { gtk_clist_select_row(GTK_CLIST(modules), x, -1); break; } } update_statusbar(buf); } free(module); } } return AST_MODULE_LOAD_SUCCESS; } static void file_ok_sel(GtkWidget *w, GtkFileSelection *fs) { char tmp[PATH_MAX]; char *module = gtk_file_selection_get_filename(fs); char buf[256]; snprintf(tmp, sizeof(tmp), "%s/", ast_config_AST_MODULE_DIR); if (!strncmp(module, (char *)tmp, strlen(tmp))) module += strlen(tmp); gdk_threads_leave(); if (ast_load_resource(module)) { snprintf(buf, sizeof(buf), "Error loading module '%s'.", module); update_statusbar(buf); } else { snprintf(buf, sizeof(buf), "Module '%s' loaded", module); update_statusbar(buf); } gdk_threads_enter(); gtk_widget_destroy(GTK_WIDGET(fs)); } static void add_module(void) { char tmp[PATH_MAX]; GtkWidget *filew; snprintf(tmp, sizeof(tmp), "%s/*.so", ast_config_AST_MODULE_DIR); filew = gtk_file_selection_new("Load Module"); gtk_signal_connect(GTK_OBJECT (GTK_FILE_SELECTION(filew)->ok_button), "clicked", GTK_SIGNAL_FUNC(file_ok_sel), filew); gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION(filew)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(filew)); gtk_file_selection_set_filename(GTK_FILE_SELECTION(filew), (char *)tmp); gtk_widget_show(filew); } static int add_mod(const char *module, const char *description, int usecount, const char *like) { char use[10]; const char *pass[4]; int row; snprintf(use, sizeof(use), "%d", usecount); pass[0] = module; pass[1] = description; pass[2] = use; pass[3] = NULL; row = gtk_clist_append(GTK_CLIST(modules), (char **) pass); gtk_clist_set_row_data(GTK_CLIST(modules), row, (char *) module); return 0; } static int mod_update(void) { char *module= NULL; /* Update the mod stuff */ if (GTK_CLIST(modules)->selection) { module= (char *)gtk_clist_get_row_data(GTK_CLIST(modules), (long) GTK_CLIST(modules)->selection->data); } gtk_clist_freeze(GTK_CLIST(modules)); gtk_clist_clear(GTK_CLIST(modules)); ast_update_module_list(add_mod, NULL); if (module) gtk_clist_select_row(GTK_CLIST(modules), gtk_clist_find_row_from_data(GTK_CLIST(modules), module), -1); gtk_clist_thaw(GTK_CLIST(modules)); return 1; } static void exit_now(GtkWidget *widget, gpointer data) { int res; ast_loader_unregister(mod_update); gtk_main_quit(); inuse--; ast_update_use_count(); res = ast_unregister_verbose(verboser); ast_unload_resource("pbx_gtkconsole", 0); ast_verb(2, "GTK Console Monitor Exiting\n"); /* XXX Trying to quit after calling this makes asterisk segfault XXX */ } static void exit_completely(GtkWidget *widget, gpointer data) { #if 0 /* Clever... */ ast_cli_command(clipipe[1], "quit"); #else kill(getpid(), SIGTERM); #endif } static void exit_nicely(GtkWidget *widget, gpointer data) { fflush(stdout); gtk_widget_destroy(window); } static void *consolethread(void *data) { gtk_widget_show(window); gdk_threads_enter(); gtk_main(); gdk_threads_leave(); return NULL; } static int cli_activate(void) { char buf[256] = ""; strncpy(buf, gtk_entry_get_text(GTK_ENTRY(cli)), sizeof(buf) - 1); gtk_entry_set_text(GTK_ENTRY(cli), ""); if (strlen(buf)) { ast_cli_command(clipipe[1], buf); } return TRUE; } static int show_console(void) { GtkWidget *hbox; GtkWidget *wbox; GtkWidget *notebook; GtkWidget *sw; GtkWidget *bbox, *hbbox, *add, *removew, *reloadw; char *modtitles[3] = { "Module", "Description", "Use Count" }; int res; window = gtk_window_new(GTK_WINDOW_TOPLEVEL); statusbar = gtk_statusbar_new(); gtk_widget_show(statusbar); gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC (exit_nicely), window); gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC (exit_now), window); gtk_container_set_border_width(GTK_CONTAINER(window), 10); quit = gtk_button_new_with_label("Quit Asterisk"); gtk_signal_connect(GTK_OBJECT(quit), "clicked", GTK_SIGNAL_FUNC (exit_completely), window); gtk_widget_show(quit); closew = gtk_button_new_with_label("Close Window"); gtk_signal_connect(GTK_OBJECT(closew), "clicked", GTK_SIGNAL_FUNC (exit_nicely), window); gtk_widget_show(closew); notebook = gtk_notebook_new(); verb = gtk_clist_new(1); gtk_clist_columns_autosize(GTK_CLIST(verb)); sw = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); gtk_container_add(GTK_CONTAINER(sw), verb); gtk_widget_show(verb); gtk_widget_show(sw); gtk_widget_set_usize(verb, 640, 400); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), sw, gtk_label_new("Verbose Status")); modules = gtk_clist_new_with_titles(3, modtitles); gtk_clist_columns_autosize(GTK_CLIST(modules)); gtk_clist_set_column_auto_resize(GTK_CLIST(modules), 0, TRUE); gtk_clist_set_column_auto_resize(GTK_CLIST(modules), 1, TRUE); gtk_clist_set_column_auto_resize(GTK_CLIST(modules), 2, TRUE); gtk_clist_set_sort_column(GTK_CLIST(modules), 0); gtk_clist_set_auto_sort(GTK_CLIST(modules), TRUE); gtk_clist_column_titles_passive(GTK_CLIST(modules)); sw = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); gtk_container_add(GTK_CONTAINER(sw), modules); gtk_clist_set_selection_mode(GTK_CLIST(modules), GTK_SELECTION_BROWSE); gtk_widget_show(modules); gtk_widget_show(sw); add = gtk_button_new_with_label("Load..."); gtk_widget_show(add); removew = gtk_button_new_with_label("Unload"); gtk_widget_show(removew); reloadw = gtk_button_new_with_label("Reload"); gtk_widget_show(reloadw); gtk_signal_connect(GTK_OBJECT(removew), "clicked", GTK_SIGNAL_FUNC (remove_module), window); gtk_signal_connect(GTK_OBJECT(add), "clicked", GTK_SIGNAL_FUNC (add_module), window); gtk_signal_connect(GTK_OBJECT(reloadw), "clicked", GTK_SIGNAL_FUNC (reload), window); bbox = gtk_vbox_new(FALSE, 5); gtk_widget_show(bbox); gtk_widget_set_usize(bbox, 100, -1); gtk_box_pack_start(GTK_BOX(bbox), add, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(bbox), removew, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(bbox), reloadw, FALSE, FALSE, 5); hbbox = gtk_hbox_new(FALSE, 5); gtk_widget_show(hbbox); gtk_box_pack_start(GTK_BOX(hbbox), sw, TRUE, TRUE, 5); gtk_box_pack_start(GTK_BOX(hbbox), bbox, FALSE, FALSE, 5); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), hbbox, gtk_label_new("Module Information")); gtk_widget_show(notebook); wbox = gtk_hbox_new(FALSE, 5); gtk_widget_show(wbox); gtk_box_pack_end(GTK_BOX(wbox), quit, FALSE, FALSE, 5); gtk_box_pack_end(GTK_BOX(wbox), closew, FALSE, FALSE, 5); hbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(hbox); /* Command line */ cli = gtk_entry_new(); gtk_widget_show(cli); gtk_signal_connect(GTK_OBJECT(cli), "activate", GTK_SIGNAL_FUNC (cli_activate), NULL); gtk_box_pack_start(GTK_BOX(hbox), notebook, TRUE, TRUE, 5); gtk_box_pack_start(GTK_BOX(hbox), wbox, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(hbox), cli, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), statusbar, FALSE, FALSE, 0); gtk_container_add(GTK_CONTAINER(window), hbox); gtk_window_set_title(GTK_WINDOW(window), "Asterisk Console"); gtk_widget_grab_focus(cli); ast_pthread_create(&console_thread, NULL, consolethread, NULL); /* XXX Okay, seriously fix me! XXX */ usleep(100000); res = ast_register_verbose(verboser); gtk_clist_freeze(GTK_CLIST(verb)); ast_loader_register(mod_update); gtk_clist_thaw(GTK_CLIST(verb)); gdk_input_add(clipipe[0], GDK_INPUT_READ, cliinput, NULL); mod_update(); update_statusbar("Asterisk Console Ready"); return 0; } static int load_module(void) { if (pipe(clipipe)) { ast_log(LOG_WARNING, "Unable to create CLI pipe\n"); return AST_MODULE_LOAD_FAILURE; } g_thread_init(NULL); if (gtk_init_check(NULL, NULL)) { if (!show_console()) { inuse++; ast_update_use_count(); ast_verb(2, "Launched GTK Console monitor\n"); } else ast_log(LOG_WARNING, "Unable to start GTK console\n"); } else { if (option_debug) ast_log(LOG_DEBUG, "Unable to start GTK console monitor -- ignoring\n"); else ast_verb(2, "GTK is not available -- skipping monitor\n"); } return AST_MODULE_LOAD_SUCCESS; } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "GTK Console", .load = load_module, .unload = unload_module, .reload = reload, ); asterisk-1.6.1.0/pbx/pbx_dundi.c0000644000175000017500000045537111163156410015672 0ustar maniacmaniac/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 1999 - 2006, Digium, Inc. * * Mark Spencer * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. */ /*! \file * * \brief Distributed Universal Number Discovery (DUNDi) */ /*** MODULEINFO zlib crypto ***/ #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision: 184631 $") #include "asterisk/network.h" #include #include #include #include #include #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__Darwin__) #include #include #endif #include "asterisk/file.h" #include "asterisk/logger.h" #include "asterisk/channel.h" #include "asterisk/config.h" #include "asterisk/pbx.h" #include "asterisk/module.h" #include "asterisk/frame.h" #include "asterisk/cli.h" #include "asterisk/lock.h" #include "asterisk/md5.h" #include "asterisk/dundi.h" #include "asterisk/sched.h" #include "asterisk/io.h" #include "asterisk/utils.h" #include "asterisk/netsock.h" #include "asterisk/crypto.h" #include "asterisk/astdb.h" #include "asterisk/acl.h" #include "asterisk/aes.h" #include "asterisk/app.h" #include "dundi-parser.h" #define MAX_RESULTS 64 #define MAX_PACKET_SIZE 8192 #define MAX_WEIGHT 59999 #define DUNDI_MODEL_INBOUND (1 << 0) #define DUNDI_MODEL_OUTBOUND (1 << 1) #define DUNDI_MODEL_SYMMETRIC (DUNDI_MODEL_INBOUND | DUNDI_MODEL_OUTBOUND) /*! Keep times of last 10 lookups */ #define DUNDI_TIMING_HISTORY 10 enum { FLAG_ISREG = (1 << 0), /*!< Transaction is register request */ FLAG_DEAD = (1 << 1), /*!< Transaction is dead */ FLAG_FINAL = (1 << 2), /*!< Transaction has final message sent */ FLAG_ISQUAL = (1 << 3), /*!< Transaction is a qualification */ FLAG_ENCRYPT = (1 << 4), /*!< Transaction is encrypted wiht ECX/DCX */ FLAG_SENDFULLKEY = (1 << 5), /*!< Send full key on transaction */ FLAG_STOREHIST = (1 << 6), /*!< Record historic performance */ }; #define DUNDI_FLAG_INTERNAL_NOPARTIAL (1 << 17) #if 0 #define DUNDI_SECRET_TIME 15 /* Testing only */ #else #define DUNDI_SECRET_TIME DUNDI_DEFAULT_CACHE_TIME #endif static struct io_context *io; static struct sched_context *sched; static int netsocket = -1; static pthread_t netthreadid = AST_PTHREADT_NULL; static pthread_t precachethreadid = AST_PTHREADT_NULL; static pthread_t clearcachethreadid = AST_PTHREADT_NULL; static unsigned int tos = 0; static int dundidebug = 0; static int authdebug = 0; static int dundi_ttl = DUNDI_DEFAULT_TTL; static int dundi_key_ttl = DUNDI_DEFAULT_KEY_EXPIRE; static int dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME; static int global_autokilltimeout = 0; static dundi_eid global_eid; static int default_expiration = 60; static int global_storehistory = 0; static char dept[80]; static char org[80]; static char locality[80]; static char stateprov[80]; static char country[80]; static char email[80]; static char phone[80]; static char secretpath[80]; static char cursecret[80]; static char ipaddr[80]; static time_t rotatetime; static dundi_eid empty_eid = { { 0, 0, 0, 0, 0, 0 } }; static int dundi_shutdown = 0; struct permission { AST_LIST_ENTRY(permission) list; int allow; char name[0]; }; struct dundi_packet { AST_LIST_ENTRY(dundi_packet) list; struct dundi_hdr *h; int datalen; struct dundi_transaction *parent; int retransid; int retrans; unsigned char data[0]; }; struct dundi_hint_metadata { unsigned short flags; char exten[AST_MAX_EXTENSION]; }; struct dundi_precache_queue { AST_LIST_ENTRY(dundi_precache_queue) list; char *context; time_t expiration; char number[0]; }; struct dundi_request; struct dundi_transaction { struct sockaddr_in addr; /*!< Other end of transaction */ struct timeval start; /*!< When this transaction was created */ dundi_eid eids[DUNDI_MAX_STACK + 1]; int eidcount; /*!< Number of eids in eids */ dundi_eid us_eid; /*!< Our EID, to them */ dundi_eid them_eid; /*!< Their EID, to us */ ast_aes_encrypt_key ecx; /*!< AES 128 Encryption context */ ast_aes_decrypt_key dcx; /*!< AES 128 Decryption context */ unsigned int flags; /*!< Has final packet been sent */ int ttl; /*!< Remaining TTL for queries on this one */ int thread; /*!< We have a calling thread */ int retranstimer; /*!< How long to wait before retransmissions */ int autokillid; /*!< ID to kill connection if answer doesn't come back fast enough */ int autokilltimeout; /*!< Recommended timeout for autokill */ unsigned short strans; /*!< Our transaction identifier */ unsigned short dtrans; /*!< Their transaction identifer */ unsigned char iseqno; /*!< Next expected received seqno */ unsigned char oiseqno; /*!< Last received incoming seqno */ unsigned char oseqno; /*!< Next transmitted seqno */ unsigned char aseqno; /*!< Last acknowledge seqno */ AST_LIST_HEAD_NOLOCK(packetlist, dundi_packet) packets; /*!< Packets to be retransmitted */ struct packetlist lasttrans; /*!< Last transmitted / ACK'd packet */ struct dundi_request *parent; /*!< Parent request (if there is one) */ AST_LIST_ENTRY(dundi_transaction) parentlist; /*!< Next with respect to the parent */ AST_LIST_ENTRY(dundi_transaction) all; /*!< Next with respect to all DUNDi transactions */ }; struct dundi_request { char dcontext[AST_MAX_EXTENSION]; char number[AST_MAX_EXTENSION]; dundi_eid query_eid; dundi_eid root_eid; struct dundi_result *dr; struct dundi_entity_info *dei; struct dundi_hint_metadata *hmd; int maxcount; int respcount; int expiration; int cbypass; int pfds[2]; uint32_t crc32; /*!< CRC-32 of all but root EID's in avoid list */ AST_LIST_HEAD_NOLOCK(, dundi_transaction) trans; /*!< Transactions */ AST_LIST_ENTRY(dundi_request) list; }; struct dundi_mapping { char dcontext[AST_MAX_EXTENSION]; char lcontext[AST_MAX_EXTENSION]; int _weight; char *weightstr; int options; int tech; int dead; char dest[AST_MAX_EXTENSION]; AST_LIST_ENTRY(dundi_mapping) list; }; struct dundi_peer { dundi_eid eid; struct sockaddr_in addr; /*!< Address of DUNDi peer */ AST_LIST_HEAD_NOLOCK(permissionlist, permission) permit; struct permissionlist include; dundi_eid us_eid; char inkey[80]; char outkey[80]; int dead; int registerid; int qualifyid; int sentfullkey; int order; unsigned char txenckey[256]; /*!< Transmitted encrypted key + sig */ unsigned char rxenckey[256]; /*!< Cache received encrypted key + sig */ uint32_t us_keycrc32; /*!< CRC-32 of our key */ ast_aes_encrypt_key us_ecx; /*!< Cached AES 128 Encryption context */ ast_aes_decrypt_key us_dcx; /*!< Cached AES 128 Decryption context */ uint32_t them_keycrc32; /*!< CRC-32 of our key */ ast_aes_encrypt_key them_ecx; /*!< Cached AES 128 Encryption context */ ast_aes_decrypt_key them_dcx; /*!< Cached AES 128 Decryption context */ time_t keyexpire; /*!< When to expire/recreate key */ int registerexpire; int lookuptimes[DUNDI_TIMING_HISTORY]; char *lookups[DUNDI_TIMING_HISTORY]; int avgms; struct dundi_transaction *regtrans; /*!< Registration transaction */ struct dundi_transaction *qualtrans; /*!< Qualify transaction */ int model; /*!< Pull model */ int pcmodel; /*!< Push/precache model */ /*! Dynamic peers register with us */ unsigned int dynamic:1; int lastms; /*!< Last measured latency */ int maxms; /*!< Max permissible latency */ struct timeval qualtx; /*!< Time of transmit */ AST_LIST_ENTRY(dundi_peer) list; }; static AST_LIST_HEAD_STATIC(peers, dundi_peer); static AST_LIST_HEAD_STATIC(pcq, dundi_precache_queue); static AST_LIST_HEAD_NOLOCK_STATIC(mappings, dundi_mapping); static AST_LIST_HEAD_NOLOCK_STATIC(requests, dundi_request); static AST_LIST_HEAD_NOLOCK_STATIC(alltrans, dundi_transaction); /*! * \brief Wildcard peer * * This peer is created if the [*] entry is specified in dundi.conf */ static struct dundi_peer *any_peer; static int dundi_xmit(struct dundi_packet *pack); static void dundi_debug_output(const char *data) { if (dundidebug) ast_verbose("%s", data); } static void dundi_error_output(const char *data) { ast_log(LOG_WARNING, "%s", data); } static int has_permission(struct permissionlist *permlist, char *cont) { struct permission *perm; int res = 0; AST_LIST_TRAVERSE(permlist, perm, list) { if (!strcasecmp(perm->name, "all") || !strcasecmp(perm->name, cont)) res = perm->allow; } return res; } static char *tech2str(int tech) { switch(tech) { case DUNDI_PROTO_NONE: return "None"; case DUNDI_PROTO_IAX: return "IAX2"; case DUNDI_PROTO_SIP: return "SIP"; case DUNDI_PROTO_H323: return "H323"; default: return "Unknown"; } } static int str2tech(char *str) { if (!strcasecmp(str, "IAX") || !strcasecmp(str, "IAX2")) return DUNDI_PROTO_IAX; else if (!strcasecmp(str, "SIP")) return DUNDI_PROTO_SIP; else if (!strcasecmp(str, "H323")) return DUNDI_PROTO_H323; else return -1; } static int dundi_lookup_internal(struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number, int ttl, int blockempty, struct dundi_hint_metadata *md, int *expiration, int cybpass, int modeselect, dundi_eid *skip, dundi_eid *avoid[], int direct[]); static int dundi_precache_internal(const char *context, const char *number, int ttl, dundi_eid *avoids[]); static struct dundi_transaction *create_transaction(struct dundi_peer *p); static struct dundi_transaction *find_transaction(struct dundi_hdr *hdr, struct sockaddr_in *sin) { struct dundi_transaction *trans; /* Look for an exact match first */ AST_LIST_TRAVERSE(&alltrans, trans, all) { if (!inaddrcmp(&trans->addr, sin) && ((trans->strans == (ntohs(hdr->dtrans) & 32767)) /* Matches our destination */ || ((trans->dtrans == (ntohs(hdr->strans) & 32767)) && (!hdr->dtrans))) /* We match their destination */) { if (hdr->strans) trans->dtrans = ntohs(hdr->strans) & 32767; return trans; } } switch(hdr->cmdresp & 0x7f) { case DUNDI_COMMAND_DPDISCOVER: case DUNDI_COMMAND_EIDQUERY: case DUNDI_COMMAND_PRECACHERQ: case DUNDI_COMMAND_REGREQ: case DUNDI_COMMAND_NULL: case DUNDI_COMMAND_ENCRYPT: if (!hdr->strans) break; /* Create new transaction */ if (!(trans = create_transaction(NULL))) break; memcpy(&trans->addr, sin, sizeof(trans->addr)); trans->dtrans = ntohs(hdr->strans) & 32767; default: break; } return trans; } static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied); static int dundi_ack(struct dundi_transaction *trans, int final) { return dundi_send(trans, DUNDI_COMMAND_ACK, 0, final, NULL); } static void dundi_reject(struct dundi_hdr *h, struct sockaddr_in *sin) { struct { struct dundi_packet pack; struct dundi_hdr hdr; } tmp; struct dundi_transaction trans; /* Never respond to an INVALID with another INVALID */ if (h->cmdresp == DUNDI_COMMAND_INVALID) return; memset(&tmp, 0, sizeof(tmp)); memset(&trans, 0, sizeof(trans)); memcpy(&trans.addr, sin, sizeof(trans.addr)); tmp.hdr.strans = h->dtrans; tmp.hdr.dtrans = h->strans; tmp.hdr.iseqno = h->oseqno; tmp.hdr.oseqno = h->iseqno; tmp.hdr.cmdresp = DUNDI_COMMAND_INVALID; tmp.hdr.cmdflags = 0; tmp.pack.h = (struct dundi_hdr *)tmp.pack.data; tmp.pack.datalen = sizeof(struct dundi_hdr); tmp.pack.parent = &trans; dundi_xmit(&tmp.pack); } static int get_trans_id(void) { struct dundi_transaction *t; int stid = (ast_random() % 32766) + 1; int tid = stid; do { AST_LIST_TRAVERSE(&alltrans, t, all) { if (t->strans == tid) break; } if (!t) return tid; tid = (tid % 32766) + 1; } while (tid != stid); return 0; } static int reset_transaction(struct dundi_transaction *trans) { int tid; tid = get_trans_id(); if (tid < 1) return -1; trans->strans = tid; trans->dtrans = 0; trans->iseqno = 0; trans->oiseqno = 0; trans->oseqno = 0; trans->aseqno = 0; ast_clear_flag(trans, FLAG_FINAL); return 0; } static struct dundi_peer *find_peer(dundi_eid *eid) { struct dundi_peer *cur = NULL; if (!eid) eid = &empty_eid; AST_LIST_TRAVERSE(&peers, cur, list) { if (!ast_eid_cmp(&cur->eid,eid)) break; } if (!cur && any_peer) cur = any_peer; return cur; } static void build_iv(unsigned char *iv) { /* XXX Would be nice to be more random XXX */ unsigned int *fluffy; int x; fluffy = (unsigned int *)(iv); for (x=0;x<4;x++) fluffy[x] = ast_random(); } struct dundi_query_state { dundi_eid *eids[DUNDI_MAX_STACK + 1]; int directs[DUNDI_MAX_STACK + 1]; dundi_eid reqeid; char called_context[AST_MAX_EXTENSION]; char called_number[AST_MAX_EXTENSION]; struct dundi_mapping *maps; int nummaps; int nocache; struct dundi_transaction *trans; void *chal; int challen; int ttl; char fluffy[0]; }; static int get_mapping_weight(struct dundi_mapping *map) { char buf[32]; buf[0] = 0; if (map->weightstr) { pbx_substitute_variables_helper(NULL, map->weightstr, buf, sizeof(buf) - 1); if (sscanf(buf, "%d", &map->_weight) != 1) map->_weight = MAX_WEIGHT; } return map->_weight; } static int dundi_lookup_local(struct dundi_result *dr, struct dundi_mapping *map, char *called_number, dundi_eid *us_eid, int anscnt, struct dundi_hint_metadata *hmd) { struct ast_flags flags = {0}; int x; if (!ast_strlen_zero(map->lcontext)) { if (ast_exists_extension(NULL, map->lcontext, called_number, 1, NULL)) ast_set_flag(&flags, DUNDI_FLAG_EXISTS); if (ast_canmatch_extension(NULL, map->lcontext, called_number, 1, NULL)) ast_set_flag(&flags, DUNDI_FLAG_CANMATCH); if (ast_matchmore_extension(NULL, map->lcontext, called_number, 1, NULL)) ast_set_flag(&flags, DUNDI_FLAG_MATCHMORE); if (ast_ignore_pattern(map->lcontext, called_number)) ast_set_flag(&flags, DUNDI_FLAG_IGNOREPAT); /* Clearly we can't say 'don't ask' anymore if we found anything... */ if (ast_test_flag(&flags, AST_FLAGS_ALL)) ast_clear_flag_nonstd(hmd, DUNDI_HINT_DONT_ASK); if (map->options & DUNDI_FLAG_INTERNAL_NOPARTIAL) { /* Skip partial answers */ ast_clear_flag(&flags, DUNDI_FLAG_MATCHMORE|DUNDI_FLAG_CANMATCH); } if (ast_test_flag(&flags, AST_FLAGS_ALL)) { struct varshead headp; struct ast_var_t *newvariable; ast_set_flag(&flags, map->options & 0xffff); ast_copy_flags(dr + anscnt, &flags, AST_FLAGS_ALL); dr[anscnt].techint = map->tech; dr[anscnt].weight = get_mapping_weight(map); dr[anscnt].expiration = dundi_cache_time; ast_copy_string(dr[anscnt].tech, tech2str(map->tech), sizeof(dr[anscnt].tech)); dr[anscnt].eid = *us_eid; ast_eid_to_str(dr[anscnt].eid_str, sizeof(dr[anscnt].eid_str), &dr[anscnt].eid); if (ast_test_flag(&flags, DUNDI_FLAG_EXISTS)) { AST_LIST_HEAD_INIT_NOLOCK(&headp); newvariable = ast_var_assign("NUMBER", called_number); AST_LIST_INSERT_HEAD(&headp, newvariable, entries); newvariable = ast_var_assign("EID", dr[anscnt].eid_str); AST_LIST_INSERT_HEAD(&headp, newvariable, entries); newvariable = ast_var_assign("SECRET", cursecret); AST_LIST_INSERT_HEAD(&headp, newvariable, entries); newvariable = ast_var_assign("IPADDR", ipaddr); AST_LIST_INSERT_HEAD(&headp, newvariable, entries); pbx_substitute_variables_varshead(&headp, map->dest, dr[anscnt].dest, sizeof(dr[anscnt].dest)); while ((newvariable = AST_LIST_REMOVE_HEAD(&headp, entries))) ast_var_delete(newvariable); } else dr[anscnt].dest[0] = '\0'; anscnt++; } else { /* No answers... Find the fewest number of digits from the number for which we have no answer. */ char tmp[AST_MAX_EXTENSION + 1] = ""; for (x = 0; x < (sizeof(tmp) - 1); x++) { tmp[x] = called_number[x]; if (!tmp[x]) break; if (!ast_canmatch_extension(NULL, map->lcontext, tmp, 1, NULL)) { /* Oops found something we can't match. If this is longer than the running hint, we have to consider it */ if (strlen(tmp) > strlen(hmd->exten)) { ast_copy_string(hmd->exten, tmp, sizeof(hmd->exten)); } break; } } } } return anscnt; } static void destroy_trans(struct dundi_transaction *trans, int fromtimeout); static void *dundi_lookup_thread(void *data) { struct dundi_query_state *st = data; struct dundi_result dr[MAX_RESULTS]; struct dundi_ie_data ied; struct dundi_hint_metadata hmd; char eid_str[20]; int res, x; int ouranswers=0; int max = 999999; int expiration = dundi_cache_time; ast_debug(1, "Whee, looking up '%s@%s' for '%s'\n", st->called_number, st->called_context, st->eids[0] ? ast_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) : "ourselves"); memset(&ied, 0, sizeof(ied)); memset(&dr, 0, sizeof(dr)); memset(&hmd, 0, sizeof(hmd)); /* Assume 'don't ask for anything' and 'unaffected', no TTL expired */ hmd.flags = DUNDI_HINT_DONT_ASK | DUNDI_HINT_UNAFFECTED; for (x=0;xnummaps;x++) ouranswers = dundi_lookup_local(dr, st->maps + x, st->called_number, &st->trans->us_eid, ouranswers, &hmd); if (ouranswers < 0) ouranswers = 0; for (x=0;xcalled_context, st->called_number, st->ttl, 1, &hmd, &expiration, st->nocache, 0, NULL, st->eids, st->directs); if (res > 0) { /* Append answer in result */ ouranswers += res; } else { if ((res < -1) && (!ouranswers)) dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_DUPLICATE, "Duplicate Request Pending"); } } AST_LIST_LOCK(&peers); /* Truncate if "don't ask" isn't present */ if (!ast_test_flag_nonstd(&hmd, DUNDI_HINT_DONT_ASK)) hmd.exten[0] = '\0'; if (ast_test_flag(st->trans, FLAG_DEAD)) { ast_debug(1, "Our transaction went away!\n"); st->trans->thread = 0; destroy_trans(st->trans, 0); } else { for (x=0;x dr[x].expiration)) expiration = dr[x].expiration; dundi_ie_append_answer(&ied, DUNDI_IE_ANSWER, &dr[x].eid, dr[x].techint, dr[x].flags, dr[x].weight, dr[x].dest); } dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten); dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, expiration); dundi_send(st->trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied); st->trans->thread = 0; } AST_LIST_UNLOCK(&peers); ast_free(st); return NULL; } static void *dundi_precache_thread(void *data) { struct dundi_query_state *st = data; struct dundi_ie_data ied; struct dundi_hint_metadata hmd; char eid_str[20]; ast_debug(1, "Whee, precaching '%s@%s' for '%s'\n", st->called_number, st->called_context, st->eids[0] ? ast_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) : "ourselves"); memset(&ied, 0, sizeof(ied)); /* Now produce precache */ dundi_precache_internal(st->called_context, st->called_number, st->ttl, st->eids); AST_LIST_LOCK(&peers); /* Truncate if "don't ask" isn't present */ if (!ast_test_flag_nonstd(&hmd, DUNDI_HINT_DONT_ASK)) hmd.exten[0] = '\0'; if (ast_test_flag(st->trans, FLAG_DEAD)) { ast_debug(1, "Our transaction went away!\n"); st->trans->thread = 0; destroy_trans(st->trans, 0); } else { dundi_send(st->trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied); st->trans->thread = 0; } AST_LIST_UNLOCK(&peers); ast_free(st); return NULL; } static int dundi_query_eid_internal(struct dundi_entity_info *dei, const char *dcontext, dundi_eid *eid, struct dundi_hint_metadata *hmd, int ttl, int blockempty, dundi_eid *avoid[]); static void *dundi_query_thread(void *data) { struct dundi_query_state *st = data; struct dundi_entity_info dei; struct dundi_ie_data ied; struct dundi_hint_metadata hmd; char eid_str[20]; int res; ast_debug(1, "Whee, looking up '%s@%s' for '%s'\n", st->called_number, st->called_context, st->eids[0] ? ast_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) : "ourselves"); memset(&ied, 0, sizeof(ied)); memset(&dei, 0, sizeof(dei)); memset(&hmd, 0, sizeof(hmd)); if (!ast_eid_cmp(&st->trans->us_eid, &st->reqeid)) { /* Ooh, it's us! */ ast_debug(1, "Neat, someone look for us!\n"); ast_copy_string(dei.orgunit, dept, sizeof(dei.orgunit)); ast_copy_string(dei.org, org, sizeof(dei.org)); ast_copy_string(dei.locality, locality, sizeof(dei.locality)); ast_copy_string(dei.stateprov, stateprov, sizeof(dei.stateprov)); ast_copy_string(dei.country, country, sizeof(dei.country)); ast_copy_string(dei.email, email, sizeof(dei.email)); ast_copy_string(dei.phone, phone, sizeof(dei.phone)); res = 1; } else { /* If we do not have a canonical result, keep looking */ res = dundi_query_eid_internal(&dei, st->called_context, &st->reqeid, &hmd, st->ttl, 1, st->eids); } AST_LIST_LOCK(&peers); if (ast_test_flag(st->trans, FLAG_DEAD)) { ast_debug(1, "Our transaction went away!\n"); st->trans->thread = 0; destroy_trans(st->trans, 0); } else { if (res) { dundi_ie_append_str(&ied, DUNDI_IE_DEPARTMENT, dei.orgunit); dundi_ie_append_str(&ied, DUNDI_IE_ORGANIZATION, dei.org); dundi_ie_append_str(&ied, DUNDI_IE_LOCALITY, dei.locality); dundi_ie_append_str(&ied, DUNDI_IE_STATE_PROV, dei.stateprov); dundi_ie_append_str(&ied, DUNDI_IE_COUNTRY, dei.country); dundi_ie_append_str(&ied, DUNDI_IE_EMAIL, dei.email); dundi_ie_append_str(&ied, DUNDI_IE_PHONE, dei.phone); if (!ast_strlen_zero(dei.ipaddr)) dundi_ie_append_str(&ied, DUNDI_IE_IPADDR, dei.ipaddr); } dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten); dundi_send(st->trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied); st->trans->thread = 0; } AST_LIST_UNLOCK(&peers); ast_free(st); return NULL; } static int dundi_answer_entity(struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext) { struct dundi_query_state *st; int totallen; int x; int skipfirst=0; char eid_str[20]; char *s; pthread_t lookupthread; if (ies->eidcount > 1) { /* Since it is a requirement that the first EID is the authenticating host and the last EID is the root, it is permissible that the first and last EID could be the same. In that case, we should go ahead copy only the "root" section since we will not need it for authentication. */ if (!ast_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1])) skipfirst = 1; } totallen = sizeof(struct dundi_query_state); totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid); st = ast_calloc(1, totallen); if (st) { ast_copy_string(st->called_context, ies->called_context, sizeof(st->called_context)); memcpy(&st->reqeid, ies->reqeid, sizeof(st->reqeid)); st->trans = trans; st->ttl = ies->ttl - 1; if (st->ttl < 0) st->ttl = 0; s = st->fluffy; for (x=skipfirst;ies->eids[x];x++) { st->eids[x-skipfirst] = (dundi_eid *)s; *st->eids[x-skipfirst] = *ies->eids[x]; s += sizeof(dundi_eid); } ast_debug(1, "Answering EID query for '%s@%s'!\n", ast_eid_to_str(eid_str, sizeof(eid_str), ies->reqeid), ies->called_context); trans->thread = 1; if (ast_pthread_create_detached(&lookupthread, NULL, dundi_query_thread, st)) { struct dundi_ie_data ied = { 0, }; trans->thread = 0; ast_log(LOG_WARNING, "Unable to create thread!\n"); ast_free(st); dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads"); dundi_send(trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied); return -1; } } else { struct dundi_ie_data ied = { 0, }; dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory"); dundi_send(trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied); return -1; } return 0; } static int cache_save_hint(dundi_eid *eidpeer, struct dundi_request *req, struct dundi_hint *hint, int expiration) { int unaffected; char key1[256]; char key2[256]; char eidpeer_str[20]; char eidroot_str[20]; char data[80]; time_t timeout; if (expiration < 0) expiration = dundi_cache_time; /* Only cache hint if "don't ask" is there... */ if (!ast_test_flag_nonstd(hint, htons(DUNDI_HINT_DONT_ASK))) return 0; unaffected = ast_test_flag_nonstd(hint, htons(DUNDI_HINT_UNAFFECTED)); dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), eidpeer); dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid); snprintf(key1, sizeof(key1), "hint/%s/%s/%s/e%08x", eidpeer_str, hint->data, req->dcontext, unaffected ? 0 : req->crc32); snprintf(key2, sizeof(key2), "hint/%s/%s/%s/r%s", eidpeer_str, hint->data, req->dcontext, eidroot_str); time(&timeout); timeout += expiration; snprintf(data, sizeof(data), "%ld|", (long)(timeout)); ast_db_put("dundi/cache", key1, data); ast_debug(1, "Caching hint at '%s'\n", key1); ast_db_put("dundi/cache", key2, data); ast_debug(1, "Caching hint at '%s'\n", key2); return 0; } static int cache_save(dundi_eid *eidpeer, struct dundi_request *req, int start, int unaffected, int expiration, int push) { int x; char key1[256]; char key2[256]; char data[1024]; char eidpeer_str[20]; char eidroot_str[20]; time_t timeout; if (expiration < 1) expiration = dundi_cache_time; /* Keep pushes a little longer, cut pulls a little short */ if (push) expiration += 10; else expiration -= 10; if (expiration < 1) expiration = 1; dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), eidpeer); dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid); snprintf(key1, sizeof(key1), "%s/%s/%s/e%08x", eidpeer_str, req->number, req->dcontext, unaffected ? 0 : req->crc32); snprintf(key2, sizeof(key2), "%s/%s/%s/r%s", eidpeer_str, req->number, req->dcontext, eidroot_str); /* Build request string */ time(&timeout); timeout += expiration; snprintf(data, sizeof(data), "%ld|", (long)(timeout)); for (x=start;xrespcount;x++) { /* Skip anything with an illegal pipe in it */ if (strchr(req->dr[x].dest, '|')) continue; snprintf(data + strlen(data), sizeof(data) - strlen(data), "%d/%d/%d/%s/%s|", req->dr[x].flags, req->dr[x].weight, req->dr[x].techint, req->dr[x].dest, dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), &req->dr[x].eid)); } ast_db_put("dundi/cache", key1, data); ast_db_put("dundi/cache", key2, data); return 0; } static int dundi_prop_precache(struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext) { struct dundi_query_state *st; int totallen; int x,z; struct dundi_ie_data ied; char *s; struct dundi_result dr2[MAX_RESULTS]; struct dundi_request dr; struct dundi_hint_metadata hmd; struct dundi_mapping *cur; int mapcount; int skipfirst = 0; pthread_t lookupthread; memset(&dr2, 0, sizeof(dr2)); memset(&dr, 0, sizeof(dr)); memset(&hmd, 0, sizeof(hmd)); /* Forge request structure to hold answers for cache */ hmd.flags = DUNDI_HINT_DONT_ASK | DUNDI_HINT_UNAFFECTED; dr.dr = dr2; dr.maxcount = MAX_RESULTS; dr.expiration = dundi_cache_time; dr.hmd = &hmd; dr.pfds[0] = dr.pfds[1] = -1; trans->parent = &dr; ast_copy_string(dr.dcontext, ies->called_context ? ies->called_context : "e164", sizeof(dr.dcontext)); ast_copy_string(dr.number, ies->called_number, sizeof(dr.number)); for (x=0;xanscount;x++) { if (trans->parent->respcount < trans->parent->maxcount) { /* Make sure it's not already there */ for (z=0;zparent->respcount;z++) { if ((trans->parent->dr[z].techint == ies->answers[x]->protocol) && !strcmp(trans->parent->dr[z].dest, (char *)ies->answers[x]->data)) break; } if (z == trans->parent->respcount) { /* Copy into parent responses */ trans->parent->dr[trans->parent->respcount].flags = ntohs(ies->answers[x]->flags); trans->parent->dr[trans->parent->respcount].techint = ies->answers[x]->protocol; trans->parent->dr[trans->parent->respcount].weight = ntohs(ies->answers[x]->weight); trans->parent->dr[trans->parent->respcount].eid = ies->answers[x]->eid; if (ies->expiration > 0) trans->parent->dr[trans->parent->respcount].expiration = ies->expiration; else trans->parent->dr[trans->parent->respcount].expiration = dundi_cache_time; ast_eid_to_str(trans->parent->dr[trans->parent->respcount].eid_str, sizeof(trans->parent->dr[trans->parent->respcount].eid_str), &ies->answers[x]->eid); ast_copy_string(trans->parent->dr[trans->parent->respcount].dest, (char *)ies->answers[x]->data, sizeof(trans->parent->dr[trans->parent->respcount].dest)); ast_copy_string(trans->parent->dr[trans->parent->respcount].tech, tech2str(ies->answers[x]->protocol), sizeof(trans->parent->dr[trans->parent->respcount].tech)); trans->parent->respcount++; ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK); } else if (trans->parent->dr[z].weight > ies->answers[x]->weight) { /* Update weight if appropriate */ trans->parent->dr[z].weight = ies->answers[x]->weight; } } else ast_log(LOG_NOTICE, "Dropping excessive answers in precache for %s@%s\n", trans->parent->number, trans->parent->dcontext); } /* Save all the results (if any) we had. Even if no results, still cache lookup. */ cache_save(&trans->them_eid, trans->parent, 0, 0, ies->expiration, 1); if (ies->hint) cache_save_hint(&trans->them_eid, trans->parent, ies->hint, ies->expiration); totallen = sizeof(struct dundi_query_state); /* Count matching map entries */ mapcount = 0; AST_LIST_TRAVERSE(&mappings, cur, list) { if (!strcasecmp(cur->dcontext, ccontext)) mapcount++; } /* If no maps, return -1 immediately */ if (!mapcount) return -1; if (ies->eidcount > 1) { /* Since it is a requirement that the first EID is the authenticating host and the last EID is the root, it is permissible that the first and last EID could be the same. In that case, we should go ahead copy only the "root" section since we will not need it for authentication. */ if (!ast_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1])) skipfirst = 1; } /* Prepare to run a query and then propagate that as necessary */ totallen += mapcount * sizeof(struct dundi_mapping); totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid); st = ast_calloc(1, totallen); if (st) { ast_copy_string(st->called_context, ies->called_context, sizeof(st->called_context)); ast_copy_string(st->called_number, ies->called_number, sizeof(st->called_number)); st->trans = trans; st->ttl = ies->ttl - 1; st->nocache = ies->cbypass; if (st->ttl < 0) st->ttl = 0; s = st->fluffy; for (x=skipfirst;ies->eids[x];x++) { st->eids[x-skipfirst] = (dundi_eid *)s; *st->eids[x-skipfirst] = *ies->eids[x]; st->directs[x-skipfirst] = ies->eid_direct[x]; s += sizeof(dundi_eid); } /* Append mappings */ x = 0; st->maps = (struct dundi_mapping *)s; AST_LIST_TRAVERSE(&mappings, cur, list) { if (!strcasecmp(cur->dcontext, ccontext)) { if (x < mapcount) { st->maps[x] = *cur; st->maps[x].list.next = NULL; x++; } } } st->nummaps = mapcount; ast_debug(1, "Forwarding precache for '%s@%s'!\n", ies->called_number, ies->called_context); trans->thread = 1; if (ast_pthread_create_detached(&lookupthread, NULL, dundi_precache_thread, st)) { trans->thread = 0; ast_log(LOG_WARNING, "Unable to create thread!\n"); ast_free(st); memset(&ied, 0, sizeof(ied)); dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads"); dundi_send(trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied); return -1; } } else { ast_log(LOG_WARNING, "Out of memory!\n"); memset(&ied, 0, sizeof(ied)); dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory"); dundi_send(trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied); return -1; } return 0; } static int dundi_answer_query(struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext) { struct dundi_query_state *st; int totallen; int x; struct dundi_ie_data ied; char *s; struct dundi_mapping *cur; int mapcount = 0; int skipfirst = 0; pthread_t lookupthread; totallen = sizeof(struct dundi_query_state); /* Count matching map entries */ AST_LIST_TRAVERSE(&mappings, cur, list) { if (!strcasecmp(cur->dcontext, ccontext)) mapcount++; } /* If no maps, return -1 immediately */ if (!mapcount) return -1; if (ies->eidcount > 1) { /* Since it is a requirement that the first EID is the authenticating host and the last EID is the root, it is permissible that the first and last EID could be the same. In that case, we should go ahead copy only the "root" section since we will not need it for authentication. */ if (!ast_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1])) skipfirst = 1; } totallen += mapcount * sizeof(struct dundi_mapping); totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid); st = ast_calloc(1, totallen); if (st) { ast_copy_string(st->called_context, ies->called_context, sizeof(st->called_context)); ast_copy_string(st->called_number, ies->called_number, sizeof(st->called_number)); st->trans = trans; st->ttl = ies->ttl - 1; st->nocache = ies->cbypass; if (st->ttl < 0) st->ttl = 0; s = st->fluffy; for (x=skipfirst;ies->eids[x];x++) { st->eids[x-skipfirst] = (dundi_eid *)s; *st->eids[x-skipfirst] = *ies->eids[x]; st->directs[x-skipfirst] = ies->eid_direct[x]; s += sizeof(dundi_eid); } /* Append mappings */ x = 0; st->maps = (struct dundi_mapping *)s; AST_LIST_TRAVERSE(&mappings, cur, list) { if (!strcasecmp(cur->dcontext, ccontext)) { if (x < mapcount) { st->maps[x] = *cur; st->maps[x].list.next = NULL; x++; } } } st->nummaps = mapcount; ast_debug(1, "Answering query for '%s@%s'!\n", ies->called_number, ies->called_context); trans->thread = 1; if (ast_pthread_create_detached(&lookupthread, NULL, dundi_lookup_thread, st)) { trans->thread = 0; ast_log(LOG_WARNING, "Unable to create thread!\n"); ast_free(st); memset(&ied, 0, sizeof(ied)); dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads"); dundi_send(trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied); return -1; } } else { ast_log(LOG_WARNING, "Out of memory!\n"); memset(&ied, 0, sizeof(ied)); dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory"); dundi_send(trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied); return -1; } return 0; } static int cache_lookup_internal(time_t now, struct dundi_request *req, char *key, char *eid_str_full, int *lowexpiration) { char data[1024]; char *ptr, *term, *src; int tech; struct ast_flags flags; int weight; int length; int z; char fs[256]; /* Build request string */ if (!ast_db_get("dundi/cache", key, data, sizeof(data))) { time_t timeout; ptr = data; if (!ast_get_time_t(ptr, &timeout, 0, &length)) { int expiration = timeout - now; if (expiration > 0) { ast_debug(1, "Found cache expiring in %d seconds!\n", expiration); ptr += length + 1; while((sscanf(ptr, "%d/%d/%d/%n", &(flags.flags), &weight, &tech, &length) == 3)) { ptr += length; term = strchr(ptr, '|'); if (term) { *term = '\0'; src = strrchr(ptr, '/'); if (src) { *src = '\0'; src++; } else src = ""; ast_debug(1, "Found cached answer '%s/%s' originally from '%s' with flags '%s' on behalf of '%s'\n", tech2str(tech), ptr, src, dundi_flags2str(fs, sizeof(fs), flags.flags), eid_str_full); /* Make sure it's not already there */ for (z=0;zrespcount;z++) { if ((req->dr[z].techint == tech) && !strcmp(req->dr[z].dest, ptr)) break; } if (z == req->respcount) { /* Copy into parent responses */ ast_copy_flags(&(req->dr[req->respcount]), &flags, AST_FLAGS_ALL); req->dr[req->respcount].weight = weight; req->dr[req->respcount].techint = tech; req->dr[req->respcount].expiration = expiration; dundi_str_short_to_eid(&req->dr[req->respcount].eid, src); ast_eid_to_str(req->dr[req->respcount].eid_str, sizeof(req->dr[req->respcount].eid_str), &req->dr[req->respcount].eid); ast_copy_string(req->dr[req->respcount].dest, ptr, sizeof(req->dr[req->respcount].dest)); ast_copy_string(req->dr[req->respcount].tech, tech2str(tech), sizeof(req->dr[req->respcount].tech)); req->respcount++; ast_clear_flag_nonstd(req->hmd, DUNDI_HINT_DONT_ASK); } else if (req->dr[z].weight > weight) req->dr[z].weight = weight; ptr = term + 1; } } /* We found *something* cached */ if (expiration < *lowexpiration) *lowexpiration = expiration; return 1; } else ast_db_del("dundi/cache", key); } else ast_db_del("dundi/cache", key); } return 0; } static int cache_lookup(struct dundi_request *req, dundi_eid *peer_eid, uint32_t crc32, int *lowexpiration) { char key[256]; char eid_str[20]; char eidroot_str[20]; time_t now; int res=0; int res2=0; char eid_str_full[20]; char tmp[256]=""; int x; time(&now); dundi_eid_to_str_short(eid_str, sizeof(eid_str), peer_eid); dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid); ast_eid_to_str(eid_str_full, sizeof(eid_str_full), peer_eid); snprintf(key, sizeof(key), "%s/%s/%s/e%08x", eid_str, req->number, req->dcontext, crc32); res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); snprintf(key, sizeof(key), "%s/%s/%s/e%08x", eid_str, req->number, req->dcontext, 0); res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); snprintf(key, sizeof(key), "%s/%s/%s/r%s", eid_str, req->number, req->dcontext, eidroot_str); res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); x = 0; if (!req->respcount) { while(!res2) { /* Look and see if we have a hint that would preclude us from looking at this peer for this number. */ if (!(tmp[x] = req->number[x])) break; x++; /* Check for hints */ snprintf(key, sizeof(key), "hint/%s/%s/%s/e%08x", eid_str, tmp, req->dcontext, crc32); res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); snprintf(key, sizeof(key), "hint/%s/%s/%s/e%08x", eid_str, tmp, req->dcontext, 0); res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); snprintf(key, sizeof(key), "hint/%s/%s/%s/r%s", eid_str, tmp, req->dcontext, eidroot_str); res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration); if (res2) { if (strlen(tmp) > strlen(req->hmd->exten)) { /* Update meta data if appropriate */ ast_copy_string(req->hmd->exten, tmp, sizeof(req->hmd->exten)); } } } res |= res2; } return res; } static void qualify_peer(struct dundi_peer *peer, int schedonly); static void apply_peer(struct dundi_transaction *trans, struct dundi_peer *p) { if (!trans->addr.sin_addr.s_addr) memcpy(&trans->addr, &p->addr, sizeof(trans->addr)); trans->us_eid = p->us_eid; trans->them_eid = p->eid; /* Enable encryption if appropriate */ if (!ast_strlen_zero(p->inkey)) ast_set_flag(trans, FLAG_ENCRYPT); if (p->maxms) { trans->autokilltimeout = p->maxms; trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER; if (p->lastms > 1) { trans->retranstimer = p->lastms * 2; /* Keep it from being silly */ if (trans->retranstimer < 150) trans->retranstimer = 150; } if (trans->retranstimer > DUNDI_DEFAULT_RETRANS_TIMER) trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER; } else trans->autokilltimeout = global_autokilltimeout; } /*! \note Called with the peers list already locked */ static int do_register_expire(const void *data) { struct dundi_peer *peer = (struct dundi_peer *)data; char eid_str[20]; ast_debug(1, "Register expired for '%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); peer->registerexpire = -1; peer->lastms = 0; memset(&peer->addr, 0, sizeof(peer->addr)); return 0; } static int update_key(struct dundi_peer *peer) { unsigned char key[16]; struct ast_key *ekey, *skey; char eid_str[20]; int res; if (!peer->keyexpire || (peer->keyexpire < time(NULL))) { build_iv(key); ast_aes_encrypt_key(key, &peer->us_ecx); ast_aes_decrypt_key(key, &peer->us_dcx); ekey = ast_key_get(peer->inkey, AST_KEY_PUBLIC); if (!ekey) { ast_log(LOG_NOTICE, "No such key '%s' for creating RSA encrypted shared key for '%s'!\n", peer->inkey, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); return -1; } skey = ast_key_get(peer->outkey, AST_KEY_PRIVATE); if (!skey) { ast_log(LOG_NOTICE, "No such key '%s' for signing RSA encrypted shared key for '%s'!\n", peer->outkey, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); return -1; } if ((res = ast_encrypt_bin(peer->txenckey, key, sizeof(key), ekey)) != 128) { ast_log(LOG_NOTICE, "Whoa, got a weird encrypt size (%d != %d)!\n", res, 128); return -1; } if ((res = ast_sign_bin(skey, (char *)peer->txenckey, 128, peer->txenckey + 128))) { ast_log(LOG_NOTICE, "Failed to sign key (%d)!\n", res); return -1; } peer->us_keycrc32 = crc32(0L, peer->txenckey, 128); peer->sentfullkey = 0; /* Looks good */ time(&peer->keyexpire); peer->keyexpire += dundi_key_ttl; } return 0; } static int encrypt_memcpy(unsigned char *dst, unsigned char *src, int len, unsigned char *iv, ast_aes_encrypt_key *ecx) { unsigned char curblock[16]; int x; memcpy(curblock, iv, sizeof(curblock)); while(len > 0) { for (x=0;x<16;x++) curblock[x] ^= src[x]; ast_aes_encrypt(curblock, dst, ecx); memcpy(curblock, dst, sizeof(curblock)); dst += 16; src += 16; len -= 16; } return 0; } static int decrypt_memcpy(unsigned char *dst, unsigned char *src, int len, unsigned char *iv, ast_aes_decrypt_key *dcx) { unsigned char lastblock[16]; int x; memcpy(lastblock, iv, sizeof(lastblock)); while(len > 0) { ast_aes_decrypt(src, dst, dcx); for (x=0;x<16;x++) dst[x] ^= lastblock[x]; memcpy(lastblock, src, sizeof(lastblock)); dst += 16; src += 16; len -= 16; } return 0; } static struct dundi_hdr *dundi_decrypt(struct dundi_transaction *trans, unsigned char *dst, int *dstlen, struct dundi_hdr *ohdr, struct dundi_encblock *src, int srclen) { int space = *dstlen; unsigned long bytes; struct dundi_hdr *h; unsigned char *decrypt_space; decrypt_space = alloca(srclen); if (!decrypt_space) return NULL; decrypt_memcpy(decrypt_space, src->encdata, srclen, src->iv, &trans->dcx); /* Setup header */ h = (struct dundi_hdr *)dst; *h = *ohdr; bytes = space - 6; if (uncompress(dst + 6, &bytes, decrypt_space, srclen) != Z_OK) { ast_debug(1, "Ouch, uncompress failed :(\n"); return NULL; } /* Update length */ *dstlen = bytes + 6; /* Return new header */ return h; } static int dundi_encrypt(struct dundi_transaction *trans, struct dundi_packet *pack) { unsigned char *compress_space; int len; int res; unsigned long bytes; struct dundi_ie_data ied; struct dundi_peer *peer; unsigned char iv[16]; len = pack->datalen + pack->datalen / 100 + 42; compress_space = alloca(len); if (compress_space) { memset(compress_space, 0, len); /* We care about everthing save the first 6 bytes of header */ bytes = len; res = compress(compress_space, &bytes, pack->data + 6, pack->datalen - 6); if (res != Z_OK) { ast_debug(1, "Ouch, compression failed!\n"); return -1; } memset(&ied, 0, sizeof(ied)); /* Say who we are */ if (!pack->h->iseqno && !pack->h->oseqno) { /* Need the key in the first copy */ if (!(peer = find_peer(&trans->them_eid))) return -1; if (update_key(peer)) return -1; if (!peer->sentfullkey) ast_set_flag(trans, FLAG_SENDFULLKEY); /* Append key data */ dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid); if (ast_test_flag(trans, FLAG_SENDFULLKEY)) { dundi_ie_append_raw(&ied, DUNDI_IE_SHAREDKEY, peer->txenckey, 128); dundi_ie_append_raw(&ied, DUNDI_IE_SIGNATURE, peer->txenckey + 128, 128); } else { dundi_ie_append_int(&ied, DUNDI_IE_KEYCRC32, peer->us_keycrc32); } /* Setup contexts */ trans->ecx = peer->us_ecx; trans->dcx = peer->us_dcx; /* We've sent the full key */ peer->sentfullkey = 1; } /* Build initialization vector */ build_iv(iv); /* Add the field, rounded up to 16 bytes */ dundi_ie_append_encdata(&ied, DUNDI_IE_ENCDATA, iv, NULL, ((bytes + 15) / 16) * 16); /* Copy the data */ if ((ied.pos + bytes) >= sizeof(ied.buf)) { ast_log(LOG_NOTICE, "Final packet too large!\n"); return -1; } encrypt_memcpy(ied.buf + ied.pos, compress_space, bytes, iv, &trans->ecx); ied.pos += ((bytes + 15) / 16) * 16; /* Reconstruct header */ pack->datalen = sizeof(struct dundi_hdr); pack->h->cmdresp = DUNDI_COMMAND_ENCRYPT; pack->h->cmdflags = 0; memcpy(pack->h->ies, ied.buf, ied.pos); pack->datalen += ied.pos; return 0; } return -1; } static int check_key(struct dundi_peer *peer, unsigned char *newkey, unsigned char *newsig, uint32_t keycrc32) { unsigned char dst[128]; int res; struct ast_key *key, *skey; char eid_str[20]; ast_debug(1, "Expected '%08x' got '%08x'\n", peer->them_keycrc32, keycrc32); if (peer->them_keycrc32 && (peer->them_keycrc32 == keycrc32)) { /* A match */ return 1; } else if (!newkey || !newsig) return 0; if (!memcmp(peer->rxenckey, newkey, 128) && !memcmp(peer->rxenckey + 128, newsig, 128)) { /* By definition, a match */ return 1; } /* Decrypt key */ key = ast_key_get(peer->outkey, AST_KEY_PRIVATE); if (!key) { ast_log(LOG_NOTICE, "Unable to find key '%s' to decode shared key from '%s'\n", peer->outkey, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); return -1; } skey = ast_key_get(peer->inkey, AST_KEY_PUBLIC); if (!skey) { ast_log(LOG_NOTICE, "Unable to find key '%s' to verify shared key from '%s'\n", peer->inkey, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); return -1; } /* First check signature */ res = ast_check_signature_bin(skey, (char *)newkey, 128, newsig); if (res) return 0; res = ast_decrypt_bin(dst, newkey, sizeof(dst), key); if (res != 16) { if (res >= 0) ast_log(LOG_NOTICE, "Weird, key decoded to the wrong size (%d)\n", res); return 0; } /* Decrypted, passes signature */ ast_debug(1, "Wow, new key combo passed signature and decrypt!\n"); memcpy(peer->rxenckey, newkey, 128); memcpy(peer->rxenckey + 128, newsig, 128); peer->them_keycrc32 = crc32(0L, peer->rxenckey, 128); ast_aes_decrypt_key(dst, &peer->them_dcx); ast_aes_encrypt_key(dst, &peer->them_ecx); return 1; } static void deep_copy_peer(struct dundi_peer *peer_dst, const struct dundi_peer *peer_src) { struct permission *cur, *perm; memcpy(peer_dst, peer_src, sizeof(*peer_dst)); memset(&peer_dst->permit, 0, sizeof(peer_dst->permit)); memset(&peer_dst->include, 0, sizeof(peer_dst->permit)); AST_LIST_TRAVERSE(&peer_src->permit, cur, list) { if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(cur->name) + 1))) continue; perm->allow = cur->allow; strcpy(perm->name, cur->name); AST_LIST_INSERT_HEAD(&peer_dst->permit, perm, list); } AST_LIST_TRAVERSE(&peer_src->include, cur, list) { if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(cur->name) + 1))) continue; perm->allow = cur->allow; strcpy(perm->name, cur->name); AST_LIST_INSERT_HEAD(&peer_dst->include, perm, list); } } static int handle_command_response(struct dundi_transaction *trans, struct dundi_hdr *hdr, int datalen, int encrypted) { /* Handle canonical command / response */ int final = hdr->cmdresp & 0x80; int cmd = hdr->cmdresp & 0x7f; int x,y,z; int resp; int res; int authpass=0; unsigned char *bufcpy; #ifdef LOW_MEMORY struct dundi_ie_data *ied = ast_calloc(1, sizeof(*ied)); #else struct dundi_ie_data _ied = { .pos = 0, }; struct dundi_ie_data *ied = &_ied; #endif struct dundi_ies ies = { .eidcount = 0, }; struct dundi_peer *peer = NULL; char eid_str[20]; char eid_str2[20]; int retval = -1; if (!ied) { return -1; } if (datalen) { bufcpy = alloca(datalen); if (!bufcpy) { goto return_cleanup; } /* Make a copy for parsing */ memcpy(bufcpy, hdr->ies, datalen); ast_debug(1, "Got canonical message %d (%d), %d bytes data%s\n", cmd, hdr->oseqno, datalen, final ? " (Final)" : ""); if (dundi_parse_ies(&ies, bufcpy, datalen) < 0) { ast_log(LOG_WARNING, "Failed to parse DUNDI information elements!\n"); goto return_cleanup; } } switch(cmd) { case DUNDI_COMMAND_DPDISCOVER: case DUNDI_COMMAND_EIDQUERY: case DUNDI_COMMAND_PRECACHERQ: if (cmd == DUNDI_COMMAND_EIDQUERY) resp = DUNDI_COMMAND_EIDRESPONSE; else if (cmd == DUNDI_COMMAND_PRECACHERQ) resp = DUNDI_COMMAND_PRECACHERP; else resp = DUNDI_COMMAND_DPRESPONSE; /* A dialplan or entity discover -- qualify by highest level entity */ peer = find_peer(ies.eids[0]); if (!peer) { dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, NULL); dundi_send(trans, resp, 0, 1, ied); } else { int hasauth = 0; trans->us_eid = peer->us_eid; if (strlen(peer->inkey)) { hasauth = encrypted; } else hasauth = 1; if (hasauth) { /* Okay we're authentiated and all, now we check if they're authorized */ if (!ies.called_context) ies.called_context = "e164"; if (cmd == DUNDI_COMMAND_EIDQUERY) { res = dundi_answer_entity(trans, &ies, ies.called_context); } else { if (ast_strlen_zero(ies.called_number)) { /* They're not permitted to access that context */ dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Invalid or missing number/entity"); dundi_send(trans, resp, 0, 1, ied); } else if ((cmd == DUNDI_COMMAND_DPDISCOVER) && (peer->model & DUNDI_MODEL_INBOUND) && has_permission(&peer->permit, ies.called_context)) { res = dundi_answer_query(trans, &ies, ies.called_context); if (res < 0) { /* There is no such dundi context */ dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unsupported DUNDI Context"); dundi_send(trans, resp, 0, 1, ied); } } else if ((cmd = DUNDI_COMMAND_PRECACHERQ) && (peer->pcmodel & DUNDI_MODEL_INBOUND) && has_permission(&peer->include, ies.called_context)) { res = dundi_prop_precache(trans, &ies, ies.called_context); if (res < 0) { /* There is no such dundi context */ dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unsupported DUNDI Context"); dundi_send(trans, resp, 0, 1, ied); } } else { /* They're not permitted to access that context */ dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Permission to context denied"); dundi_send(trans, resp, 0, 1, ied); } } } else { /* They're not permitted to access that context */ dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unencrypted responses not permitted"); dundi_send(trans, resp, 0, 1, ied); } } break; case DUNDI_COMMAND_REGREQ: /* A register request -- should only have one entity */ peer = find_peer(ies.eids[0]); /* if the peer is not found and we have a valid 'any_peer' setting */ if (any_peer && peer == any_peer) { /* copy any_peer into a new peer object */ peer = ast_calloc(1, sizeof(*peer)); if (peer) { deep_copy_peer(peer, any_peer); /* set EID to remote EID */ peer->eid = *ies.eids[0]; AST_LIST_LOCK(&peers); AST_LIST_INSERT_HEAD(&peers, peer, list); AST_LIST_UNLOCK(&peers); } } if (!peer || !peer->dynamic) { dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, NULL); dundi_send(trans, DUNDI_COMMAND_REGRESPONSE, 0, 1, ied); } else { int hasauth = 0; trans->us_eid = peer->us_eid; if (!ast_strlen_zero(peer->inkey)) { hasauth = encrypted; } else hasauth = 1; if (hasauth) { int expire = default_expiration; char data[256]; int needqual = 0; AST_SCHED_DEL(sched, peer->registerexpire); peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer); snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(trans->addr.sin_addr), ntohs(trans->addr.sin_port), expire); ast_db_put("dundi/dpeers", dundi_eid_to_str_short(eid_str, sizeof(eid_str), &peer->eid), data); if (inaddrcmp(&peer->addr, &trans->addr)) { ast_verb(3, "Registered DUNDi peer '%s' at '%s:%d'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), ast_inet_ntoa(trans->addr.sin_addr), ntohs(trans->addr.sin_port)); needqual = 1; } memcpy(&peer->addr, &trans->addr, sizeof(peer->addr)); dundi_ie_append_short(ied, DUNDI_IE_EXPIRATION, default_expiration); dundi_send(trans, DUNDI_COMMAND_REGRESPONSE, 0, 1, ied); if (needqual) qualify_peer(peer, 1); } } break; case DUNDI_COMMAND_DPRESPONSE: /* A dialplan response, lets see what we got... */ if (ies.cause < 1) { /* Success of some sort */ ast_debug(1, "Looks like success of some sort (%d), %d answers\n", ies.cause, ies.anscount); if (ast_test_flag(trans, FLAG_ENCRYPT)) { authpass = encrypted; } else authpass = 1; if (authpass) { /* Pass back up answers */ if (trans->parent && trans->parent->dr) { y = trans->parent->respcount; for (x=0;xparent->respcount < trans->parent->maxcount) { /* Make sure it's not already there */ for (z=0;zparent->respcount;z++) { if ((trans->parent->dr[z].techint == ies.answers[x]->protocol) && !strcmp(trans->parent->dr[z].dest, (char *)ies.answers[x]->data)) break; } if (z == trans->parent->respcount) { /* Copy into parent responses */ trans->parent->dr[trans->parent->respcount].flags = ntohs(ies.answers[x]->flags); trans->parent->dr[trans->parent->respcount].techint = ies.answers[x]->protocol; trans->parent->dr[trans->parent->respcount].weight = ntohs(ies.answers[x]->weight); trans->parent->dr[trans->parent->respcount].eid = ies.answers[x]->eid; if (ies.expiration > 0) trans->parent->dr[trans->parent->respcount].expiration = ies.expiration; else trans->parent->dr[trans->parent->respcount].expiration = dundi_cache_time; ast_eid_to_str(trans->parent->dr[trans->parent->respcount].eid_str, sizeof(trans->parent->dr[trans->parent->respcount].eid_str), &ies.answers[x]->eid); ast_copy_string(trans->parent->dr[trans->parent->respcount].dest, (char *)ies.answers[x]->data, sizeof(trans->parent->dr[trans->parent->respcount].dest)); ast_copy_string(trans->parent->dr[trans->parent->respcount].tech, tech2str(ies.answers[x]->protocol), sizeof(trans->parent->dr[trans->parent->respcount].tech)); trans->parent->respcount++; ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK); } else if (trans->parent->dr[z].weight > ies.answers[x]->weight) { /* Update weight if appropriate */ trans->parent->dr[z].weight = ies.answers[x]->weight; } } else ast_log(LOG_NOTICE, "Dropping excessive answers to request for %s@%s\n", trans->parent->number, trans->parent->dcontext); } /* Save all the results (if any) we had. Even if no results, still cache lookup. Let the cache know if this request was unaffected by our entity list. */ cache_save(&trans->them_eid, trans->parent, y, ies.hint ? ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_UNAFFECTED)) : 0, ies.expiration, 0); if (ies.hint) { cache_save_hint(&trans->them_eid, trans->parent, ies.hint, ies.expiration); if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_TTL_EXPIRED))) ast_set_flag_nonstd(trans->parent->hmd, DUNDI_HINT_TTL_EXPIRED); if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_DONT_ASK))) { if (strlen((char *)ies.hint->data) > strlen(trans->parent->hmd->exten)) { ast_copy_string(trans->parent->hmd->exten, (char *)ies.hint->data, sizeof(trans->parent->hmd->exten)); } } else { ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK); } } if (ies.expiration > 0) { if (trans->parent->expiration > ies.expiration) { trans->parent->expiration = ies.expiration; } } } /* Close connection if not final */ if (!final) dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); } } else { /* Auth failure, check for data */ if (!final) { /* Cancel if they didn't already */ dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); } } break; case DUNDI_COMMAND_EIDRESPONSE: /* A dialplan response, lets see what we got... */ if (ies.cause < 1) { /* Success of some sort */ ast_debug(1, "Looks like success of some sort (%d)\n", ies.cause); if (ast_test_flag(trans, FLAG_ENCRYPT)) { authpass = encrypted; } else authpass = 1; if (authpass) { /* Pass back up answers */ if (trans->parent && trans->parent->dei && ies.q_org) { if (!trans->parent->respcount) { trans->parent->respcount++; if (ies.q_dept) ast_copy_string(trans->parent->dei->orgunit, ies.q_dept, sizeof(trans->parent->dei->orgunit)); if (ies.q_org) ast_copy_string(trans->parent->dei->org, ies.q_org, sizeof(trans->parent->dei->org)); if (ies.q_locality) ast_copy_string(trans->parent->dei->locality, ies.q_locality, sizeof(trans->parent->dei->locality)); if (ies.q_stateprov) ast_copy_string(trans->parent->dei->stateprov, ies.q_stateprov, sizeof(trans->parent->dei->stateprov)); if (ies.q_country) ast_copy_string(trans->parent->dei->country, ies.q_country, sizeof(trans->parent->dei->country)); if (ies.q_email) ast_copy_string(trans->parent->dei->email, ies.q_email, sizeof(trans->parent->dei->email)); if (ies.q_phone) ast_copy_string(trans->parent->dei->phone, ies.q_phone, sizeof(trans->parent->dei->phone)); if (ies.q_ipaddr) ast_copy_string(trans->parent->dei->ipaddr, ies.q_ipaddr, sizeof(trans->parent->dei->ipaddr)); if (!ast_eid_cmp(&trans->them_eid, &trans->parent->query_eid)) { /* If it's them, update our address */ ast_copy_string(trans->parent->dei->ipaddr, ast_inet_ntoa(trans->addr.sin_addr), sizeof(trans->parent->dei->ipaddr)); } } if (ies.hint) { if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_TTL_EXPIRED))) ast_set_flag_nonstd(trans->parent->hmd, DUNDI_HINT_TTL_EXPIRED); } } /* Close connection if not final */ if (!final) dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); } } else { /* Auth failure, check for data */ if (!final) { /* Cancel if they didn't already */ dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); } } break; case DUNDI_COMMAND_REGRESPONSE: /* A dialplan response, lets see what we got... */ if (ies.cause < 1) { int hasauth; /* Success of some sort */ if (ast_test_flag(trans, FLAG_ENCRYPT)) { hasauth = encrypted; } else hasauth = 1; if (!hasauth) { ast_log(LOG_NOTICE, "Reponse to register not authorized!\n"); if (!final) { dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Improper signature in answer"); dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, ied); } } else { ast_debug(1, "Yay, we've registered as '%s' to '%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &trans->us_eid), ast_eid_to_str(eid_str2, sizeof(eid_str2), &trans->them_eid)); /* Close connection if not final */ if (!final) dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); } } else { /* Auth failure, cancel if they didn't for some reason */ if (!final) { dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); } } break; case DUNDI_COMMAND_INVALID: case DUNDI_COMMAND_NULL: case DUNDI_COMMAND_PRECACHERP: /* Do nothing special */ if (!final) dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); break; case DUNDI_COMMAND_ENCREJ: if ((ast_test_flag(trans, FLAG_SENDFULLKEY)) || AST_LIST_EMPTY(&trans->lasttrans) || !(peer = find_peer(&trans->them_eid))) { /* No really, it's over at this point */ if (!final) dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); } else { /* Send with full key */ ast_set_flag(trans, FLAG_SENDFULLKEY); if (final) { /* Ooops, we got a final message, start by sending ACK... */ dundi_ack(trans, hdr->cmdresp & 0x80); trans->aseqno = trans->iseqno; /* Now, we gotta create a new transaction */ if (!reset_transaction(trans)) { /* Make sure handle_frame doesn't destroy us */ hdr->cmdresp &= 0x7f; /* Parse the message we transmitted */ memset(&ies, 0, sizeof(ies)); dundi_parse_ies(&ies, (AST_LIST_FIRST(&trans->lasttrans))->h->ies, (AST_LIST_FIRST(&trans->lasttrans))->datalen - sizeof(struct dundi_hdr)); /* Reconstruct outgoing encrypted packet */ memset(ied, 0, sizeof(*ied)); dundi_ie_append_eid(ied, DUNDI_IE_EID, &trans->us_eid); dundi_ie_append_raw(ied, DUNDI_IE_SHAREDKEY, peer->txenckey, 128); dundi_ie_append_raw(ied, DUNDI_IE_SIGNATURE, peer->txenckey + 128, 128); if (ies.encblock) dundi_ie_append_encdata(ied, DUNDI_IE_ENCDATA, ies.encblock->iv, ies.encblock->encdata, ies.enclen); dundi_send(trans, DUNDI_COMMAND_ENCRYPT, 0, (AST_LIST_FIRST(&trans->lasttrans))->h->cmdresp & 0x80, ied); peer->sentfullkey = 1; } } } break; case DUNDI_COMMAND_ENCRYPT: if (!encrypted) { /* No nested encryption! */ if ((trans->iseqno == 1) && !trans->oseqno) { if (!ies.eids[0] || !(peer = find_peer(ies.eids[0])) || ((!ies.encsharedkey || !ies.encsig) && !ies.keycrc32) || (check_key(peer, ies.encsharedkey, ies.encsig, ies.keycrc32) < 1)) { if (!final) { dundi_send(trans, DUNDI_COMMAND_ENCREJ, 0, 1, NULL); } break; } apply_peer(trans, peer); /* Key passed, use new contexts for this session */ trans->ecx = peer->them_ecx; trans->dcx = peer->them_dcx; } if (ast_test_flag(trans, FLAG_ENCRYPT) && ies.encblock && ies.enclen) { struct dundi_hdr *dhdr; unsigned char decoded[MAX_PACKET_SIZE]; int ddatalen; ddatalen = sizeof(decoded); dhdr = dundi_decrypt(trans, decoded, &ddatalen, hdr, ies.encblock, ies.enclen); if (dhdr) { /* Handle decrypted response */ if (dundidebug) dundi_showframe(dhdr, 3, &trans->addr, ddatalen - sizeof(struct dundi_hdr)); handle_command_response(trans, dhdr, ddatalen - sizeof(struct dundi_hdr), 1); /* Carry back final flag */ hdr->cmdresp |= dhdr->cmdresp & 0x80; break; } else { ast_debug(1, "Ouch, decrypt failed :(\n"); } } } if (!final) { /* Turn off encryption */ ast_clear_flag(trans, FLAG_ENCRYPT); dundi_send(trans, DUNDI_COMMAND_ENCREJ, 0, 1, NULL); } break; default: /* Send unknown command if we don't know it, with final flag IFF it's the first command in the dialog and only if we haven't recieved final notification */ if (!final) { dundi_ie_append_byte(ied, DUNDI_IE_UNKNOWN, cmd); dundi_send(trans, DUNDI_COMMAND_UNKNOWN, 0, !hdr->oseqno, ied); } } retval = 0; return_cleanup: #ifdef LOW_MEMORY ast_free(ied); #endif return retval; } static void destroy_packet(struct dundi_packet *pack, int needfree); static void destroy_packets(struct packetlist *p) { struct dundi_packet *pack; while ((pack = AST_LIST_REMOVE_HEAD(p, list))) { AST_SCHED_DEL(sched, pack->retransid); ast_free(pack); } } static int ack_trans(struct dundi_transaction *trans, int iseqno) { struct dundi_packet *pack; /* Ack transmitted packet corresponding to iseqno */ AST_LIST_TRAVERSE(&trans->packets, pack, list) { if ((pack->h->oseqno + 1) % 255 == iseqno) { destroy_packet(pack, 0); if (!AST_LIST_EMPTY(&trans->lasttrans)) { ast_log(LOG_WARNING, "Whoa, there was still a last trans?\n"); destroy_packets(&trans->lasttrans); } AST_LIST_INSERT_HEAD(&trans->lasttrans, pack, list); AST_SCHED_DEL(sched, trans->autokillid); return 1; } } return 0; } static int handle_frame(struct dundi_hdr *h, struct sockaddr_in *sin, int datalen) { struct dundi_transaction *trans; trans = find_transaction(h, sin); if (!trans) { dundi_reject(h, sin); return 0; } /* Got a transaction, see where this header fits in */ if (h->oseqno == trans->iseqno) { /* Just what we were looking for... Anything but ack increments iseqno */ if (ack_trans(trans, h->iseqno) && ast_test_flag(trans, FLAG_FINAL)) { /* If final, we're done */ destroy_trans(trans, 0); return 0; } if (h->cmdresp != DUNDI_COMMAND_ACK) { trans->oiseqno = trans->iseqno; trans->iseqno++; handle_command_response(trans, h, datalen, 0); } if (trans->aseqno != trans->iseqno) { dundi_ack(trans, h->cmdresp & 0x80); trans->aseqno = trans->iseqno; } /* Delete any saved last transmissions */ destroy_packets(&trans->lasttrans); if (h->cmdresp & 0x80) { /* Final -- destroy now */ destroy_trans(trans, 0); } } else if (h->oseqno == trans->oiseqno) { /* Last incoming sequence number -- send ACK without processing */ dundi_ack(trans, 0); } else { /* Out of window -- simply drop */ ast_debug(1, "Dropping packet out of window!\n"); } return 0; } static int socket_read(int *id, int fd, short events, void *cbdata) { struct sockaddr_in sin; int res; struct dundi_hdr *h; char buf[MAX_PACKET_SIZE]; socklen_t len = sizeof(sin); res = recvfrom(netsocket, buf, sizeof(buf) - 1, 0,(struct sockaddr *) &sin, &len); if (res < 0) { if (errno != ECONNREFUSED) ast_log(LOG_WARNING, "Error: %s\n", strerror(errno)); return 1; } if (res < sizeof(struct dundi_hdr)) { ast_log(LOG_WARNING, "midget packet received (%d of %d min)\n", res, (int)sizeof(struct dundi_hdr)); return 1; } buf[res] = '\0'; h = (struct dundi_hdr *) buf; if (dundidebug) dundi_showframe(h, 1, &sin, res - sizeof(struct dundi_hdr)); AST_LIST_LOCK(&peers); handle_frame(h, &sin, res - sizeof(struct dundi_hdr)); AST_LIST_UNLOCK(&peers); return 1; } static void build_secret(char *secret, int seclen) { unsigned char tmp[16]; char *s; build_iv(tmp); secret[0] = '\0'; ast_base64encode(secret, tmp, sizeof(tmp), seclen); /* Eliminate potential bad characters */ while((s = strchr(secret, ';'))) *s = '+'; while((s = strchr(secret, '/'))) *s = '+'; while((s = strchr(secret, ':'))) *s = '+'; while((s = strchr(secret, '@'))) *s = '+'; } static void save_secret(const char *newkey, const char *oldkey) { char tmp[256]; if (oldkey) snprintf(tmp, sizeof(tmp), "%s;%s", oldkey, newkey); else snprintf(tmp, sizeof(tmp), "%s", newkey); rotatetime = time(NULL) + DUNDI_SECRET_TIME; ast_db_put(secretpath, "secret", tmp); snprintf(tmp, sizeof(tmp), "%d", (int)rotatetime); ast_db_put(secretpath, "secretexpiry", tmp); } static void load_password(void) { char *current=NULL; char *last=NULL; char tmp[256]; time_t expired; ast_db_get(secretpath, "secretexpiry", tmp, sizeof(tmp)); if (!ast_get_time_t(tmp, &expired, 0, NULL)) { ast_db_get(secretpath, "secret", tmp, sizeof(tmp)); current = strchr(tmp, ';'); if (!current) current = tmp; else { *current = '\0'; current++; }; if ((time(NULL) - expired) < 0) { if ((expired - time(NULL)) > DUNDI_SECRET_TIME) expired = time(NULL) + DUNDI_SECRET_TIME; } else if ((time(NULL) - (expired + DUNDI_SECRET_TIME)) < 0) { last = current; current = NULL; } else { last = NULL; current = NULL; } } if (current) { /* Current key is still valid, just setup rotatation properly */ ast_copy_string(cursecret, current, sizeof(cursecret)); rotatetime = expired; } else { /* Current key is out of date, rotate or eliminate all together */ build_secret(cursecret, sizeof(cursecret)); save_secret(cursecret, last); } } static void check_password(void) { char oldsecret[80]; time_t now; time(&now); #if 0 printf("%ld/%ld\n", now, rotatetime); #endif if ((now - rotatetime) >= 0) { /* Time to rotate keys */ ast_copy_string(oldsecret, cursecret, sizeof(oldsecret)); build_secret(cursecret, sizeof(cursecret)); save_secret(cursecret, oldsecret); } } static void *network_thread(void *ignore) { /* Our job is simple: Send queued messages, retrying if necessary. Read frames from the network, and queue them for delivery to the channels */ int res; /* Establish I/O callback for socket read */ ast_io_add(io, netsocket, socket_read, AST_IO_IN, NULL); while (!dundi_shutdown) { res = ast_sched_wait(sched); if ((res > 1000) || (res < 0)) res = 1000; res = ast_io_wait(io, res); if (res >= 0) { AST_LIST_LOCK(&peers); ast_sched_runq(sched); AST_LIST_UNLOCK(&peers); } check_password(); } netthreadid = AST_PTHREADT_NULL; return NULL; } static void *process_clearcache(void *ignore) { struct ast_db_entry *db_entry, *db_tree; int striplen = sizeof("/dundi/cache"); time_t now; while (!dundi_shutdown) { pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); time(&now); db_entry = db_tree = ast_db_gettree("dundi/cache", NULL); for (; db_entry; db_entry = db_entry->next) { time_t expiry; if (!ast_get_time_t(db_entry->data, &expiry, 0, NULL)) { if (expiry < now) { ast_debug(1, "clearing expired DUNDI cache entry: %s\n", db_entry->key); ast_db_del("dundi/cache", db_entry->key + striplen); } } } ast_db_freetree(db_tree); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_testcancel(); sleep(60); pthread_testcancel(); } clearcachethreadid = AST_PTHREADT_NULL; return NULL; } static void *process_precache(void *ign) { struct dundi_precache_queue *qe; time_t now; char context[256]; char number[256]; int run; while (!dundi_shutdown) { time(&now); run = 0; AST_LIST_LOCK(&pcq); if ((qe = AST_LIST_FIRST(&pcq))) { if (!qe->expiration) { /* Gone... Remove... */ AST_LIST_REMOVE_HEAD(&pcq, list); ast_free(qe); } else if (qe->expiration < now) { /* Process this entry */ qe->expiration = 0; ast_copy_string(context, qe->context, sizeof(context)); ast_copy_string(number, qe->number, sizeof(number)); run = 1; } } AST_LIST_UNLOCK(&pcq); if (run) { dundi_precache(context, number); } else sleep(1); } precachethreadid = AST_PTHREADT_NULL; return NULL; } static int start_network_thread(void) { ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL); ast_pthread_create_background(&precachethreadid, NULL, process_precache, NULL); ast_pthread_create_background(&clearcachethreadid, NULL, process_clearcache, NULL); return 0; } static char *dundi_do_debug_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { switch (cmd) { case CLI_INIT: e->command = "dundi [no] debug"; e->usage = "Usage: dundi [no] debug\n" " Enables/Disables dumping of DUNDi packets for debugging purposes\n"; return NULL; case CLI_GENERATE: return NULL; } if (a->argc < 2 || a->argc > 3) return CLI_SHOWUSAGE; if (a->argc == 2) { dundidebug = 1; ast_cli(a->fd, "DUNDi Debugging Enabled\n"); } else { dundidebug = 0; ast_cli(a->fd, "DUNDi Debugging Disabled\n"); } return CLI_SUCCESS; } static char *dundi_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { switch (cmd) { case CLI_INIT: e->command = "dundi set debug {on|off}"; e->usage = "Usage: dundi set debug {on|off}\n" " Enables/Disables dumping of DUNDi packets for debugging purposes\n"; return NULL; case CLI_GENERATE: return NULL; } if (a->argc != e->args) return CLI_SHOWUSAGE; if (!strncasecmp(a->argv[e->args -1], "on", 2)) { dundidebug = 1; ast_cli(a->fd, "DUNDi Debugging Enabled\n"); } else { dundidebug = 0; ast_cli(a->fd, "DUNDi Debugging Disabled\n"); } return CLI_SUCCESS; } static char *dundi_do_store_history_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { switch (cmd) { case CLI_INIT: e->command = "dundi [no] store history"; e->usage = "Usage: dundi [no] store history\n" " Enables/Disables storing of DUNDi requests and times for debugging\n" "purposes\n"; return NULL; case CLI_GENERATE: return NULL; } if (a->argc < 3 || a->argc > 4) return CLI_SHOWUSAGE; if (a->argc == 3) { global_storehistory = 1; ast_cli(a->fd, "DUNDi History Storage Enabled\n"); } else { global_storehistory = 0; ast_cli(a->fd, "DUNDi History Storage Disabled\n"); } return CLI_SUCCESS; } static char *dundi_store_history(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { switch (cmd) { case CLI_INIT: e->command = "dundi store history {on|off}"; e->usage = "Usage: dundi store history {on|off}\n" " Enables/Disables storing of DUNDi requests and times for debugging\n" "purposes\n"; return NULL; case CLI_GENERATE: return NULL; } if (a->argc != e->args) return CLI_SHOWUSAGE; if (!strncasecmp(a->argv[e->args -1], "on", 2)) { global_storehistory = 1; ast_cli(a->fd, "DUNDi History Storage Enabled\n"); } else { global_storehistory = 0; ast_cli(a->fd, "DUNDi History Storage Disabled\n"); } return CLI_SUCCESS; } static char *dundi_flush(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { int stats = 0; switch (cmd) { case CLI_INIT: e->command = "dundi flush [stats]"; e->usage = "Usage: dundi flush [stats]\n" " Flushes DUNDi answer cache, used primarily for debug. If\n" "'stats' is present, clears timer statistics instead of normal\n" "operation.\n"; return NULL; case CLI_GENERATE: return NULL; } if ((a->argc < 2) || (a->argc > 3)) return CLI_SHOWUSAGE; if (a->argc > 2) { if (!strcasecmp(a->argv[2], "stats")) stats = 1; else return CLI_SHOWUSAGE; } if (stats) { /* Flush statistics */ struct dundi_peer *p; int x; AST_LIST_LOCK(&peers); AST_LIST_TRAVERSE(&peers, p, list) { for (x = 0;x < DUNDI_TIMING_HISTORY; x++) { if (p->lookups[x]) ast_free(p->lookups[x]); p->lookups[x] = NULL; p->lookuptimes[x] = 0; } p->avgms = 0; } AST_LIST_UNLOCK(&peers); } else { ast_db_deltree("dundi/cache", NULL); ast_cli(a->fd, "DUNDi Cache Flushed\n"); } return CLI_SUCCESS; } static char *model2str(int model) { switch(model) { case DUNDI_MODEL_INBOUND: return "Inbound"; case DUNDI_MODEL_OUTBOUND: return "Outbound"; case DUNDI_MODEL_SYMMETRIC: return "Symmetric"; default: return "Unknown"; } } static char *complete_peer_helper(const char *line, const char *word, int pos, int state, int rpos) { int which=0, len; char *ret = NULL; struct dundi_peer *p; char eid_str[20]; if (pos != rpos) return NULL; AST_LIST_LOCK(&peers); len = strlen(word); AST_LIST_TRAVERSE(&peers, p, list) { const char *s = ast_eid_to_str(eid_str, sizeof(eid_str), &p->eid); if (!strncasecmp(word, s, len) && ++which > state) { ret = ast_strdup(s); break; } } AST_LIST_UNLOCK(&peers); return ret; } static int rescomp(const void *a, const void *b) { const struct dundi_result *resa, *resb; resa = a; resb = b; if (resa->weight < resb->weight) return -1; if (resa->weight > resb->weight) return 1; return 0; } static void sort_results(struct dundi_result *results, int count) { qsort(results, count, sizeof(results[0]), rescomp); } static char *dundi_do_lookup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { int res; char tmp[256]; char fs[80] = ""; char *context; int x; int bypass = 0; struct dundi_result dr[MAX_RESULTS]; struct timeval start; switch (cmd) { case CLI_INIT: e->command = "dundi lookup"; e->usage = "Usage: dundi lookup [@context] [bypass]\n" " Lookup the given number within the given DUNDi context\n" "(or e164 if none is specified). Bypasses cache if 'bypass'\n" "keyword is specified.\n"; return NULL; case CLI_GENERATE: return NULL; } if ((a->argc < 3) || (a->argc > 4)) return CLI_SHOWUSAGE; if (a->argc > 3) { if (!strcasecmp(a->argv[3], "bypass")) bypass=1; else return CLI_SHOWUSAGE; } ast_copy_string(tmp, a->argv[2], sizeof(tmp)); context = strchr(tmp, '@'); if (context) { *context = '\0'; context++; } start = ast_tvnow(); res = dundi_lookup(dr, MAX_RESULTS, NULL, context, tmp, bypass); if (res < 0) ast_cli(a->fd, "DUNDi lookup returned error.\n"); else if (!res) ast_cli(a->fd, "DUNDi lookup returned no results.\n"); else sort_results(dr, res); for (x=0;xfd, "%3d. %5d %s/%s (%s)\n", x + 1, dr[x].weight, dr[x].tech, dr[x].dest, dundi_flags2str(fs, sizeof(fs), dr[x].flags)); ast_cli(a->fd, " from %s, expires in %d s\n", dr[x].eid_str, dr[x].expiration); } ast_cli(a->fd, "DUNDi lookup completed in %d ms\n", ast_tvdiff_ms(ast_tvnow(), start)); return CLI_SUCCESS; } static char *dundi_do_precache(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { int res; char tmp[256]; char *context; struct timeval start; switch (cmd) { case CLI_INIT: e->command = "dundi precache"; e->usage = "Usage: dundi precache [@context]\n" " Lookup the given number within the given DUNDi context\n" "(or e164 if none is specified) and precaches the results to any\n" "upstream DUNDi push servers.\n"; return NULL; case CLI_GENERATE: return NULL; } if ((a->argc < 3) || (a->argc > 3)) return CLI_SHOWUSAGE; ast_copy_string(tmp, a->argv[2], sizeof(tmp)); context = strchr(tmp, '@'); if (context) { *context = '\0'; context++; } start = ast_tvnow(); res = dundi_precache(context, tmp); if (res < 0) ast_cli(a->fd, "DUNDi precache returned error.\n"); else if (!res) ast_cli(a->fd, "DUNDi precache returned no error.\n"); ast_cli(a->fd, "DUNDi lookup completed in %d ms\n", ast_tvdiff_ms(ast_tvnow(), start)); return CLI_SUCCESS; } static char *dundi_do_query(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { int res; char tmp[256]; char *context; dundi_eid eid; struct dundi_entity_info dei; switch (cmd) { case CLI_INIT: e->command = "dundi query"; e->usage = "Usage: dundi query [@context]\n" " Attempts to retrieve contact information for a specific\n" "DUNDi entity identifier (EID) within a given DUNDi context (or\n" "e164 if none is specified).\n"; return NULL; case CLI_GENERATE: return NULL; } if ((a->argc < 3) || (a->argc > 3)) return CLI_SHOWUSAGE; if (ast_str_to_eid(&eid, a->argv[2])) { ast_cli(a->fd, "'%s' is not a valid EID!\n", a->argv[2]); return CLI_SHOWUSAGE; } ast_copy_string(tmp, a->argv[2], sizeof(tmp)); context = strchr(tmp, '@'); if (context) { *context = '\0'; context++; } res = dundi_query_eid(&dei, context, eid); if (res < 0) ast_cli(a->fd, "DUNDi Query EID returned error.\n"); else if (!res) ast_cli(a->fd, "DUNDi Query EID returned no results.\n"); else { ast_cli(a->fd, "DUNDi Query EID succeeded:\n"); ast_cli(a->fd, "Department: %s\n", dei.orgunit); ast_cli(a->fd, "Organization: %s\n", dei.org); ast_cli(a->fd, "City/Locality: %s\n", dei.locality); ast_cli(a->fd, "State/Province: %s\n", dei.stateprov); ast_cli(a->fd, "Country: %s\n", dei.country); ast_cli(a->fd, "E-mail: %s\n", dei.email); ast_cli(a->fd, "Phone: %s\n", dei.phone); ast_cli(a->fd, "IP Address: %s\n", dei.ipaddr); } return CLI_SUCCESS; } static char *dundi_show_peer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { struct dundi_peer *peer; struct permission *p; char *order; char eid_str[20]; int x, cnt; switch (cmd) { case CLI_INIT: e->command = "dundi show peer"; e->usage = "Usage: dundi show peer [peer]\n" " Provide a detailed description of a specifid DUNDi peer.\n"; return NULL; case CLI_GENERATE: return complete_peer_helper(a->line, a->word, a->pos, a->n, 3); } if (a->argc != 4) return CLI_SHOWUSAGE; AST_LIST_LOCK(&peers); AST_LIST_TRAVERSE(&peers, peer, list) { if (!strcasecmp(ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), a->argv[3])) break; } if (peer) { switch(peer->order) { case 0: order = "Primary"; break; case 1: order = "Secondary"; break; case 2: order = "Tertiary"; break; case 3: order = "Quartiary"; break; default: order = "Unknown"; } ast_cli(a->fd, "Peer: %s\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); ast_cli(a->fd, "Model: %s\n", model2str(peer->model)); ast_cli(a->fd, "Host: %s\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : ""); ast_cli(a->fd, "Dynamic: %s\n", peer->dynamic ? "yes" : "no"); ast_cli(a->fd, "Reg: %s\n", peer->registerid < 0 ? "No" : "Yes"); ast_cli(a->fd, "In Key: %s\n", ast_strlen_zero(peer->inkey) ? "" : peer->inkey); ast_cli(a->fd, "Out Key: %s\n", ast_strlen_zero(peer->outkey) ? "" : peer->outkey); if (!AST_LIST_EMPTY(&peer->include)) ast_cli(a->fd, "Include logic%s:\n", peer->model & DUNDI_MODEL_OUTBOUND ? "" : " (IGNORED)"); AST_LIST_TRAVERSE(&peer->include, p, list) ast_cli(a->fd, "-- %s %s\n", p->allow ? "include" : "do not include", p->name); if (!AST_LIST_EMPTY(&peer->permit)) ast_cli(a->fd, "Query logic%s:\n", peer->model & DUNDI_MODEL_INBOUND ? "" : " (IGNORED)"); AST_LIST_TRAVERSE(&peer->permit, p, list) ast_cli(a->fd, "-- %s %s\n", p->allow ? "permit" : "deny", p->name); cnt = 0; for (x = 0;x < DUNDI_TIMING_HISTORY; x++) { if (peer->lookups[x]) { if (!cnt) ast_cli(a->fd, "Last few query times:\n"); ast_cli(a->fd, "-- %d. %s (%d ms)\n", x + 1, peer->lookups[x], peer->lookuptimes[x]); cnt++; } } if (cnt) ast_cli(a->fd, "Average query time: %d ms\n", peer->avgms); } else ast_cli(a->fd, "No such peer '%s'\n", a->argv[3]); AST_LIST_UNLOCK(&peers); return CLI_SUCCESS; } static char *dundi_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { #define FORMAT2 "%-20.20s %-15.15s %-10.10s %-8.8s %-15.15s\n" #define FORMAT "%-20.20s %-15.15s %s %-10.10s %-8.8s %-15.15s\n" struct dundi_peer *peer; int registeredonly=0; char avgms[20]; char eid_str[20]; int online_peers = 0; int offline_peers = 0; int unmonitored_peers = 0; int total_peers = 0; switch (cmd) { case CLI_INIT: e->command = "dundi show peers [registered|include|exclude|begin]"; e->usage = "Usage: dundi show peers [registered|include|exclude|begin]\n" " Lists all known DUNDi peers.\n" " If 'registered' is present, only registered peers are shown.\n"; return NULL; case CLI_GENERATE: return NULL; } if ((a->argc != 3) && (a->argc != 4) && (a->argc != 5)) return CLI_SHOWUSAGE; if ((a->argc == 4)) { if (!strcasecmp(a->argv[3], "registered")) { registeredonly = 1; } else return CLI_SHOWUSAGE; } AST_LIST_LOCK(&peers); ast_cli(a->fd, FORMAT2, "EID", "Host", "Model", "AvgTime", "Status"); AST_LIST_TRAVERSE(&peers, peer, list) { char status[20]; int print_line = -1; char srch[2000]; total_peers++; if (registeredonly && !peer->addr.sin_addr.s_addr) continue; if (peer->maxms) { if (peer->lastms < 0) { strcpy(status, "UNREACHABLE"); offline_peers++; } else if (peer->lastms > peer->maxms) { snprintf(status, sizeof(status), "LAGGED (%d ms)", peer->lastms); offline_peers++; } else if (peer->lastms) { snprintf(status, sizeof(status), "OK (%d ms)", peer->lastms); online_peers++; } else { strcpy(status, "UNKNOWN"); offline_peers++; } } else { strcpy(status, "Unmonitored"); unmonitored_peers++; } if (peer->avgms) snprintf(avgms, sizeof(avgms), "%d ms", peer->avgms); else strcpy(avgms, "Unavail"); snprintf(srch, sizeof(srch), FORMAT, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", peer->dynamic ? "(D)" : "(S)", model2str(peer->model), avgms, status); if (a->argc == 5) { if (!strcasecmp(a->argv[3],"include") && strstr(srch,a->argv[4])) { print_line = -1; } else if (!strcasecmp(a->argv[3],"exclude") && !strstr(srch,a->argv[4])) { print_line = 1; } else if (!strcasecmp(a->argv[3],"begin") && !strncasecmp(srch,a->argv[4],strlen(a->argv[4]))) { print_line = -1; } else { print_line = 0; } } if (print_line) { ast_cli(a->fd, FORMAT, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", peer->dynamic ? "(D)" : "(S)", model2str(peer->model), avgms, status); } } ast_cli(a->fd, "%d dundi peers [%d online, %d offline, %d unmonitored]\n", total_peers, online_peers, offline_peers, unmonitored_peers); AST_LIST_UNLOCK(&peers); return CLI_SUCCESS; #undef FORMAT #undef FORMAT2 } static char *dundi_show_trans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { #define FORMAT2 "%-22.22s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n" #define FORMAT "%-16.16s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n" struct dundi_transaction *trans; switch (cmd) { case CLI_INIT: e->command = "dundi show trans"; e->usage = "Usage: dundi show trans\n" " Lists all known DUNDi transactions.\n"; return NULL; case CLI_GENERATE: return NULL; } if (a->argc != 3) return CLI_SHOWUSAGE; AST_LIST_LOCK(&peers); ast_cli(a->fd, FORMAT2, "Remote", "Src", "Dst", "Tx", "Rx", "Ack"); AST_LIST_TRAVERSE(&alltrans, trans, all) { ast_cli(a->fd, FORMAT, ast_inet_ntoa(trans->addr.sin_addr), ntohs(trans->addr.sin_port), trans->strans, trans->dtrans, trans->oseqno, trans->iseqno, trans->aseqno); } AST_LIST_UNLOCK(&peers); return CLI_SUCCESS; #undef FORMAT #undef FORMAT2 } static char *dundi_show_entityid(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { char eid_str[20]; switch (cmd) { case CLI_INIT: e->command = "dundi show entityid"; e->usage = "Usage: dundi show entityid\n" " Displays the global entityid for this host.\n"; return NULL; case CLI_GENERATE: return NULL; } if (a->argc != 3) return CLI_SHOWUSAGE; AST_LIST_LOCK(&peers); ast_eid_to_str(eid_str, sizeof(eid_str), &global_eid); AST_LIST_UNLOCK(&peers); ast_cli(a->fd, "Global EID for this system is '%s'\n", eid_str); return CLI_SUCCESS; } static char *dundi_show_requests(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { #define FORMAT2 "%-15s %-15s %-15s %-3.3s %-3.3s\n" #define FORMAT "%-15s %-15s %-15s %-3.3d %-3.3d\n" struct dundi_request *req; char eidstr[20]; switch (cmd) { case CLI_INIT: e->command = "dundi show requests"; e->usage = "Usage: dundi show requests\n" " Lists all known pending DUNDi requests.\n"; return NULL; case CLI_GENERATE: return NULL; } if (a->argc != 3) return CLI_SHOWUSAGE; AST_LIST_LOCK(&peers); ast_cli(a->fd, FORMAT2, "Number", "Context", "Root", "Max", "Rsp"); AST_LIST_TRAVERSE(&requests, req, list) { ast_cli(a->fd, FORMAT, req->number, req->dcontext, dundi_eid_zero(&req->root_eid) ? "" : ast_eid_to_str(eidstr, sizeof(eidstr), &req->root_eid), req->maxcount, req->respcount); } AST_LIST_UNLOCK(&peers); return CLI_SUCCESS; #undef FORMAT #undef FORMAT2 } /* Grok-a-dial DUNDi */ static char *dundi_show_mappings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { #define FORMAT2 "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n" #define FORMAT "%-12.12s %-7s %-12.12s %-10.10s %-5.5s %-25.25s\n" struct dundi_mapping *map; char fs[256]; char weight[8]; switch (cmd) { case CLI_INIT: e->command = "dundi show mappings"; e->usage = "Usage: dundi show mappings\n" " Lists all known DUNDi mappings.\n"; return NULL; case CLI_GENERATE: return NULL; } if (a->argc != 3) return CLI_SHOWUSAGE; AST_LIST_LOCK(&peers); ast_cli(a->fd, FORMAT2, "DUNDi Cntxt", "Weight", "Local Cntxt", "Options", "Tech", "Destination"); AST_LIST_TRAVERSE(&mappings, map, list) { snprintf(weight, sizeof(weight), "%d", get_mapping_weight(map)); ast_cli(a->fd, FORMAT, map->dcontext, weight, ast_strlen_zero(map->lcontext) ? "" : map->lcontext, dundi_flags2str(fs, sizeof(fs), map->options), tech2str(map->tech), map->dest); } AST_LIST_UNLOCK(&peers); return CLI_SUCCESS; #undef FORMAT #undef FORMAT2 } static char *dundi_show_precache(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { #define FORMAT2 "%-12.12s %-12.12s %-10.10s\n" #define FORMAT "%-12.12s %-12.12s %02d:%02d:%02d\n" struct dundi_precache_queue *qe; int h,m,s; time_t now; switch (cmd) { case CLI_INIT: e->command = "dundi show precache"; e->usage = "Usage: dundi show precache\n" " Lists all known DUNDi scheduled precache updates.\n"; return NULL; case CLI_GENERATE: return NULL; } if (a->argc != 3) return CLI_SHOWUSAGE; time(&now); ast_cli(a->fd, FORMAT2, "Number", "Context", "Expiration"); AST_LIST_LOCK(&pcq); AST_LIST_TRAVERSE(&pcq, qe, list) { s = qe->expiration - now; h = s / 3600; s = s % 3600; m = s / 60; s = s % 60; ast_cli(a->fd, FORMAT, qe->number, qe->context, h,m,s); } AST_LIST_UNLOCK(&pcq); return CLI_SUCCESS; #undef FORMAT #undef FORMAT2 } static struct ast_cli_entry cli_dundi_do_debug_deprecated = AST_CLI_DEFINE(dundi_do_debug_deprecated, "Enable/Disable DUNDi debugging"); static struct ast_cli_entry cli_dundi_do_store_history_deprecated = AST_CLI_DEFINE(dundi_do_store_history_deprecated, "Enable/Disable DUNDi historic records"); static struct ast_cli_entry cli_dundi[] = { AST_CLI_DEFINE(dundi_set_debug, "Enable/Disable DUNDi debugging", .deprecate_cmd = &cli_dundi_do_debug_deprecated), AST_CLI_DEFINE(dundi_store_history, "Enable/Disable DUNDi historic records", .deprecate_cmd = &cli_dundi_do_store_history_deprecated), AST_CLI_DEFINE(dundi_flush, "Flush DUNDi cache"), AST_CLI_DEFINE(dundi_show_peers, "Show defined DUNDi peers"), AST_CLI_DEFINE(dundi_show_trans, "Show active DUNDi transactions"), AST_CLI_DEFINE(dundi_show_entityid, "Display Global Entity ID"), AST_CLI_DEFINE(dundi_show_mappings, "Show DUNDi mappings"), AST_CLI_DEFINE(dundi_show_precache, "Show DUNDi precache"), AST_CLI_DEFINE(dundi_show_requests, "Show DUNDi requests"), AST_CLI_DEFINE(dundi_show_peer, "Show info on a specific DUNDi peer"), AST_CLI_DEFINE(dundi_do_precache, "Precache a number in DUNDi"), AST_CLI_DEFINE(dundi_do_lookup, "Lookup a number in DUNDi"), AST_CLI_DEFINE(dundi_do_query, "Query a DUNDi EID"), }; static struct dundi_transaction *create_transaction(struct dundi_peer *p) { struct dundi_transaction *trans; int tid; /* Don't allow creation of transactions to non-registered peers */ if (p && !p->addr.sin_addr.s_addr) return NULL; tid = get_trans_id(); if (tid < 1) return NULL; if (!(trans = ast_calloc(1, sizeof(*trans)))) return NULL; if (global_storehistory) { trans->start = ast_tvnow(); ast_set_flag(trans, FLAG_STOREHIST); } trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER; trans->autokillid = -1; if (p) { apply_peer(trans, p); if (!p->sentfullkey) ast_set_flag(trans, FLAG_SENDFULLKEY); } trans->strans = tid; AST_LIST_INSERT_HEAD(&alltrans, trans, all); return trans; } static int dundi_xmit(struct dundi_packet *pack) { int res; if (dundidebug) dundi_showframe(pack->h, 0, &pack->parent->addr, pack->datalen - sizeof(struct dundi_hdr)); res = sendto(netsocket, pack->data, pack->datalen, 0, (struct sockaddr *)&pack->parent->addr, sizeof(pack->parent->addr)); if (res < 0) { ast_log(LOG_WARNING, "Failed to transmit to '%s:%d': %s\n", ast_inet_ntoa(pack->parent->addr.sin_addr), ntohs(pack->parent->addr.sin_port), strerror(errno)); } if (res > 0) res = 0; return res; } static void destroy_packet(struct dundi_packet *pack, int needfree) { if (pack->parent) AST_LIST_REMOVE(&pack->parent->packets, pack, list); AST_SCHED_DEL(sched, pack->retransid); if (needfree) ast_free(pack); } static void destroy_trans(struct dundi_transaction *trans, int fromtimeout) { struct dundi_peer *peer; int ms; int x; int cnt; char eid_str[20]; if (ast_test_flag(trans, FLAG_ISREG | FLAG_ISQUAL | FLAG_STOREHIST)) { AST_LIST_TRAVERSE(&peers, peer, list) { if (peer->regtrans == trans) peer->regtrans = NULL; if (peer->qualtrans == trans) { if (fromtimeout) { if (peer->lastms > -1) ast_log(LOG_NOTICE, "Peer '%s' has become UNREACHABLE!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); peer->lastms = -1; } else { ms = ast_tvdiff_ms(ast_tvnow(), peer->qualtx); if (ms < 1) ms = 1; if (ms < peer->maxms) { if ((peer->lastms >= peer->maxms) || (peer->lastms < 0)) ast_log(LOG_NOTICE, "Peer '%s' has become REACHABLE!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); } else if (peer->lastms < peer->maxms) { ast_log(LOG_NOTICE, "Peer '%s' has become TOO LAGGED (%d ms)\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), ms); } peer->lastms = ms; } peer->qualtrans = NULL; } if (ast_test_flag(trans, FLAG_STOREHIST)) { if (trans->parent && !ast_strlen_zero(trans->parent->number)) { if (!ast_eid_cmp(&trans->them_eid, &peer->eid)) { peer->avgms = 0; cnt = 0; if (peer->lookups[DUNDI_TIMING_HISTORY-1]) ast_free(peer->lookups[DUNDI_TIMING_HISTORY-1]); for (x=DUNDI_TIMING_HISTORY-1;x>0;x--) { peer->lookuptimes[x] = peer->lookuptimes[x-1]; peer->lookups[x] = peer->lookups[x-1]; if (peer->lookups[x]) { peer->avgms += peer->lookuptimes[x]; cnt++; } } peer->lookuptimes[0] = ast_tvdiff_ms(ast_tvnow(), trans->start); peer->lookups[0] = ast_malloc(strlen(trans->parent->number) + strlen(trans->parent->dcontext) + 2); if (peer->lookups[0]) { sprintf(peer->lookups[0], "%s@%s", trans->parent->number, trans->parent->dcontext); peer->avgms += peer->lookuptimes[0]; cnt++; } if (cnt) peer->avgms /= cnt; } } } } } if (trans->parent) { /* Unlink from parent if appropriate */ AST_LIST_REMOVE(&trans->parent->trans, trans, parentlist); if (AST_LIST_EMPTY(&trans->parent->trans)) { /* Wake up sleeper */ if (trans->parent->pfds[1] > -1) { if (write(trans->parent->pfds[1], "killa!", 6) < 0) { ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); } } } } /* Unlink from all trans */ AST_LIST_REMOVE(&alltrans, trans, all); destroy_packets(&trans->packets); destroy_packets(&trans->lasttrans); AST_SCHED_DEL(sched, trans->autokillid); if (trans->thread) { /* If used by a thread, mark as dead and be done */ ast_set_flag(trans, FLAG_DEAD); } else ast_free(trans); } static int dundi_rexmit(const void *data) { struct dundi_packet *pack = (struct dundi_packet *)data; int res; AST_LIST_LOCK(&peers); if (pack->retrans < 1) { pack->retransid = -1; if (!ast_test_flag(pack->parent, FLAG_ISQUAL)) ast_log(LOG_NOTICE, "Max retries exceeded to host '%s:%d' msg %d on call %d\n", ast_inet_ntoa(pack->parent->addr.sin_addr), ntohs(pack->parent->addr.sin_port), pack->h->oseqno, ntohs(pack->h->strans)); destroy_trans(pack->parent, 1); res = 0; } else { /* Decrement retransmission, try again */ pack->retrans--; dundi_xmit(pack); res = 1; } AST_LIST_UNLOCK(&peers); return res; } static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied) { struct dundi_packet *pack; int res; int len; char eid_str[20]; len = sizeof(struct dundi_packet) + sizeof(struct dundi_hdr) + (ied ? ied->pos : 0); /* Reserve enough space for encryption */ if (ast_test_flag(trans, FLAG_ENCRYPT)) len += 384; pack = ast_calloc(1, len); if (pack) { pack->h = (struct dundi_hdr *)(pack->data); if (cmdresp != DUNDI_COMMAND_ACK) { pack->retransid = ast_sched_add(sched, trans->retranstimer, dundi_rexmit, pack); pack->retrans = DUNDI_DEFAULT_RETRANS - 1; AST_LIST_INSERT_HEAD(&trans->packets, pack, list); } pack->parent = trans; pack->h->strans = htons(trans->strans); pack->h->dtrans = htons(trans->dtrans); pack->h->iseqno = trans->iseqno; pack->h->oseqno = trans->oseqno; pack->h->cmdresp = cmdresp; pack->datalen = sizeof(struct dundi_hdr); if (ied) { memcpy(pack->h->ies, ied->buf, ied->pos); pack->datalen += ied->pos; } if (final) { pack->h->cmdresp |= DUNDI_COMMAND_FINAL; ast_set_flag(trans, FLAG_FINAL); } pack->h->cmdflags = flags; if (cmdresp != DUNDI_COMMAND_ACK) { trans->oseqno++; trans->oseqno = trans->oseqno % 256; } trans->aseqno = trans->iseqno; /* If we have their public key, encrypt */ if (ast_test_flag(trans, FLAG_ENCRYPT)) { switch(cmdresp) { case DUNDI_COMMAND_REGREQ: case DUNDI_COMMAND_REGRESPONSE: case DUNDI_COMMAND_DPDISCOVER: case DUNDI_COMMAND_DPRESPONSE: case DUNDI_COMMAND_EIDQUERY: case DUNDI_COMMAND_EIDRESPONSE: case DUNDI_COMMAND_PRECACHERQ: case DUNDI_COMMAND_PRECACHERP: if (dundidebug) dundi_showframe(pack->h, 2, &trans->addr, pack->datalen - sizeof(struct dundi_hdr)); res = dundi_encrypt(trans, pack); break; default: res = 0; } } else res = 0; if (!res) res = dundi_xmit(pack); if (res) ast_log(LOG_NOTICE, "Failed to send packet to '%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid)); if (cmdresp == DUNDI_COMMAND_ACK) ast_free(pack); return res; } return -1; } static int do_autokill(const void *data) { struct dundi_transaction *trans = (struct dundi_transaction *)data; char eid_str[20]; ast_log(LOG_NOTICE, "Transaction to '%s' took too long to ACK, destroying\n", ast_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid)); trans->autokillid = -1; destroy_trans(trans, 0); /* We could actually set it to 1 instead of 0, but we won't ;-) */ return 0; } static void dundi_ie_append_eid_appropriately(struct dundi_ie_data *ied, char *context, dundi_eid *eid, dundi_eid *us) { struct dundi_peer *p; if (!ast_eid_cmp(eid, us)) { dundi_ie_append_eid(ied, DUNDI_IE_EID_DIRECT, eid); return; } AST_LIST_LOCK(&peers); AST_LIST_TRAVERSE(&peers, p, list) { if (!ast_eid_cmp(&p->eid, eid)) { if (has_permission(&p->include, context)) dundi_ie_append_eid(ied, DUNDI_IE_EID_DIRECT, eid); else dundi_ie_append_eid(ied, DUNDI_IE_EID, eid); break; } } if (!p) dundi_ie_append_eid(ied, DUNDI_IE_EID, eid); AST_LIST_UNLOCK(&peers); } static int dundi_discover(struct dundi_transaction *trans) { struct dundi_ie_data ied; int x; if (!trans->parent) { ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n"); return -1; } memset(&ied, 0, sizeof(ied)); dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION); if (!dundi_eid_zero(&trans->us_eid)) dundi_ie_append_eid(&ied, DUNDI_IE_EID_DIRECT, &trans->us_eid); for (x=0;xeidcount;x++) dundi_ie_append_eid_appropriately(&ied, trans->parent->dcontext, &trans->eids[x], &trans->us_eid); dundi_ie_append_str(&ied, DUNDI_IE_CALLED_NUMBER, trans->parent->number); dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext); dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl); if (trans->parent->cbypass) dundi_ie_append(&ied, DUNDI_IE_CACHEBYPASS); if (trans->autokilltimeout) trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans); return dundi_send(trans, DUNDI_COMMAND_DPDISCOVER, 0, 0, &ied); } static int precache_trans(struct dundi_transaction *trans, struct dundi_mapping *maps, int mapcount, int *minexp, int *foundanswers) { struct dundi_ie_data ied; int x, res; int max = 999999; int expiration = dundi_cache_time; int ouranswers=0; dundi_eid *avoid[1] = { NULL, }; int direct[1] = { 0, }; struct dundi_result dr[MAX_RESULTS]; struct dundi_hint_metadata hmd; if (!trans->parent) { ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n"); return -1; } memset(&hmd, 0, sizeof(hmd)); memset(&dr, 0, sizeof(dr)); /* Look up the answers we're going to include */ for (x=0;xparent->number, &trans->us_eid, ouranswers, &hmd); if (ouranswers < 0) ouranswers = 0; for (x=0;xparent->dcontext, trans->parent->number, trans->ttl, 1, &hmd, &expiration, 0, 1, &trans->them_eid, avoid, direct); if (res > 0) { /* Append answer in result */ ouranswers += res; } } if (ouranswers > 0) { *foundanswers += ouranswers; memset(&ied, 0, sizeof(ied)); dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION); if (!dundi_eid_zero(&trans->us_eid)) dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid); for (x=0;xeidcount;x++) dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->eids[x]); dundi_ie_append_str(&ied, DUNDI_IE_CALLED_NUMBER, trans->parent->number); dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext); dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl); for (x=0;x dr[x].expiration)) expiration = dr[x].expiration; dundi_ie_append_answer(&ied, DUNDI_IE_ANSWER, &dr[x].eid, dr[x].techint, dr[x].flags, dr[x].weight, dr[x].dest); } dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten); dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, expiration); if (trans->autokilltimeout) trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans); if (expiration < *minexp) *minexp = expiration; return dundi_send(trans, DUNDI_COMMAND_PRECACHERQ, 0, 0, &ied); } else { /* Oops, nothing to send... */ destroy_trans(trans, 0); return 0; } } static int dundi_query(struct dundi_transaction *trans) { struct dundi_ie_data ied; int x; if (!trans->parent) { ast_log(LOG_WARNING, "Tried to query a transaction with no parent?!?\n"); return -1; } memset(&ied, 0, sizeof(ied)); dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION); if (!dundi_eid_zero(&trans->us_eid)) dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid); for (x=0;xeidcount;x++) dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->eids[x]); dundi_ie_append_eid(&ied, DUNDI_IE_REQEID, &trans->parent->query_eid); dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext); dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl); if (trans->autokilltimeout) trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans); return dundi_send(trans, DUNDI_COMMAND_EIDQUERY, 0, 0, &ied); } static int discover_transactions(struct dundi_request *dr) { struct dundi_transaction *trans; AST_LIST_LOCK(&peers); AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { dundi_discover(trans); } AST_LIST_UNLOCK(&peers); return 0; } static int precache_transactions(struct dundi_request *dr, struct dundi_mapping *maps, int mapcount, int *expiration, int *foundanswers) { struct dundi_transaction *trans; /* Mark all as "in thread" so they don't disappear */ AST_LIST_LOCK(&peers); AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { if (trans->thread) ast_log(LOG_WARNING, "This shouldn't happen, really...\n"); trans->thread = 1; } AST_LIST_UNLOCK(&peers); AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { if (!ast_test_flag(trans, FLAG_DEAD)) precache_trans(trans, maps, mapcount, expiration, foundanswers); } /* Cleanup any that got destroyed in the mean time */ AST_LIST_LOCK(&peers); AST_LIST_TRAVERSE_SAFE_BEGIN(&dr->trans, trans, parentlist) { trans->thread = 0; if (ast_test_flag(trans, FLAG_DEAD)) { ast_debug(1, "Our transaction went away!\n"); /* This is going to remove the transaction from the dundi_request's list, as well * as the global transactions list */ destroy_trans(trans, 0); } } AST_LIST_TRAVERSE_SAFE_END AST_LIST_UNLOCK(&peers); return 0; } static int query_transactions(struct dundi_request *dr) { struct dundi_transaction *trans; AST_LIST_LOCK(&peers); AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { dundi_query(trans); } AST_LIST_UNLOCK(&peers); return 0; } static int optimize_transactions(struct dundi_request *dr, int order) { /* Minimize the message propagation through DUNDi by alerting the network to hops which should be not be considered */ struct dundi_transaction *trans; struct dundi_peer *peer; dundi_eid tmp; int x; int needpush; AST_LIST_LOCK(&peers); AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) { /* Pop off the true root */ if (trans->eidcount) { tmp = trans->eids[--trans->eidcount]; needpush = 1; } else { tmp = trans->us_eid; needpush = 0; } AST_LIST_TRAVERSE(&peers, peer, list) { if (has_permission(&peer->include, dr->dcontext) && ast_eid_cmp(&peer->eid, &trans->them_eid) && (peer->order <= order)) { /* For each other transaction, make sure we don't ask this EID about the others if they're not already in the list */ if (!ast_eid_cmp(&tmp, &peer->eid)) x = -1; else { for (x=0;xeidcount;x++) { if (!ast_eid_cmp(&trans->eids[x], &peer->eid)) break; } } if (x == trans->eidcount) { /* Nope not in the list, if needed, add us at the end since we're the source */ if (trans->eidcount < DUNDI_MAX_STACK - needpush) { trans->eids[trans->eidcount++] = peer->eid; /* Need to insert the real root (or us) at the bottom now as a requirement now. */ needpush = 1; } } } } /* If necessary, push the true root back on the end */ if (needpush) trans->eids[trans->eidcount++] = tmp; } AST_LIST_UNLOCK(&peers); return 0; } static int append_transaction(struct dundi_request *dr, struct dundi_peer *p, int ttl, dundi_eid *avoid[]) { struct dundi_transaction *trans; int x; char eid_str[20]; char eid_str2[20]; /* Ignore if not registered */ if (!p->addr.sin_addr.s_addr) return 0; if (p->maxms && ((p->lastms < 0) || (p->lastms >= p->maxms))) return 0; if (ast_strlen_zero(dr->number)) ast_debug(1, "Will query peer '%s' for '%s' (context '%s')\n", ast_eid_to_str(eid_str, sizeof(eid_str), &p->eid), ast_eid_to_str(eid_str2, sizeof(eid_str2), &dr->query_eid), dr->dcontext); else ast_debug(1, "Will query peer '%s' for '%s@%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &p->eid), dr->number, dr->dcontext); trans = create_transaction(p); if (!trans) return -1; trans->parent = dr; trans->ttl = ttl; for (x = 0; avoid[x] && (x < DUNDI_MAX_STACK); x++) trans->eids[x] = *avoid[x]; trans->eidcount = x; AST_LIST_INSERT_HEAD(&dr->trans, trans, parentlist); return 0; } static void cancel_request(struct dundi_request *dr) { struct dundi_transaction *trans; AST_LIST_LOCK(&peers); while ((trans = AST_LIST_REMOVE_HEAD(&dr->trans, parentlist))) { /* Orphan transaction from request */ trans->parent = NULL; /* Send final cancel */ dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL); } AST_LIST_UNLOCK(&peers); } static void abort_request(struct dundi_request *dr) { struct dundi_transaction *trans; AST_LIST_LOCK(&peers); while ((trans = AST_LIST_FIRST(&dr->trans))) { /* This will remove the transaction from the list */ destroy_trans(trans, 0); } AST_LIST_UNLOCK(&peers); } static void build_transactions(struct dundi_request *dr, int ttl, int order, int *foundcache, int *skipped, int blockempty, int nocache, int modeselect, dundi_eid *skip, dundi_eid *avoid[], int directs[]) { struct dundi_peer *p; int x; int res; int pass; int allowconnect; char eid_str[20]; AST_LIST_LOCK(&peers); AST_LIST_TRAVERSE(&peers, p, list) { if (modeselect == 1) { /* Send the precache to push upstreams only! */ pass = has_permission(&p->permit, dr->dcontext) && (p->pcmodel & DUNDI_MODEL_OUTBOUND); allowconnect = 1; } else { /* Normal lookup / EID query */ pass = has_permission(&p->include, dr->dcontext); allowconnect = p->model & DUNDI_MODEL_OUTBOUND; } if (skip) { if (!ast_eid_cmp(skip, &p->eid)) pass = 0; } if (pass) { if (p->order <= order) { /* Check order first, then check cache, regardless of omissions, this gets us more likely to not have an affected answer. */ if((nocache || !(res = cache_lookup(dr, &p->eid, dr->crc32, &dr->expiration)))) { res = 0; /* Make sure we haven't already seen it and that it won't affect our answer */ for (x=0;avoid[x];x++) { if (!ast_eid_cmp(avoid[x], &p->eid) || !ast_eid_cmp(avoid[x], &p->us_eid)) { /* If not a direct connection, it affects our answer */ if (directs && !directs[x]) ast_clear_flag_nonstd(dr->hmd, DUNDI_HINT_UNAFFECTED); break; } } /* Make sure we can ask */ if (allowconnect) { if (!avoid[x] && (!blockempty || !dundi_eid_zero(&p->us_eid))) { /* Check for a matching or 0 cache entry */ append_transaction(dr, p, ttl, avoid); } else { ast_debug(1, "Avoiding '%s' in transaction\n", ast_eid_to_str(eid_str, sizeof(eid_str), avoid[x])); } } } *foundcache |= res; } else if (!*skipped || (p->order < *skipped)) *skipped = p->order; } } AST_LIST_UNLOCK(&peers); } static int register_request(struct dundi_request *dr, struct dundi_request **pending) { struct dundi_request *cur; int res=0; char eid_str[20]; AST_LIST_LOCK(&peers); AST_LIST_TRAVERSE(&requests, cur, list) { ast_debug(1, "Checking '%s@%s' vs '%s@%s'\n", cur->dcontext, cur->number, dr->dcontext, dr->number); if (!strcasecmp(cur->dcontext, dr->dcontext) && !strcasecmp(cur->number, dr->number) && (!ast_eid_cmp(&cur->root_eid, &dr->root_eid) || (cur->crc32 == dr->crc32))) { ast_debug(1, "Found existing query for '%s@%s' for '%s' crc '%08x'\n", cur->dcontext, cur->number, ast_eid_to_str(eid_str, sizeof(eid_str), &cur->root_eid), cur->crc32); *pending = cur; res = 1; break; } } if (!res) { ast_debug(1, "Registering request for '%s@%s' on behalf of '%s' crc '%08x'\n", dr->number, dr->dcontext, ast_eid_to_str(eid_str, sizeof(eid_str), &dr->root_eid), dr->crc32); /* Go ahead and link us in since nobody else is searching for this */ AST_LIST_INSERT_HEAD(&requests, dr, list); *pending = NULL; } AST_LIST_UNLOCK(&peers); return res; } static void unregister_request(struct dundi_request *dr) { AST_LIST_LOCK(&peers); AST_LIST_REMOVE(&requests, dr, list); AST_LIST_UNLOCK(&peers); } static int check_request(struct dundi_request *dr) { struct dundi_request *cur; AST_LIST_LOCK(&peers); AST_LIST_TRAVERSE(&requests, cur, list) { if (cur == dr) break; } AST_LIST_UNLOCK(&peers); return cur ? 1 : 0; } static unsigned long avoid_crc32(dundi_eid *avoid[]) { /* Idea is that we're calculating a checksum which is independent of the order that the EID's are listed in */ uint32_t acrc32 = 0; int x; for (x=0;avoid[x];x++) { /* Order doesn't matter */ if (avoid[x+1]) { acrc32 ^= crc32(0L, (unsigned char *)avoid[x], sizeof(dundi_eid)); } } return acrc32; } static int dundi_lookup_internal(struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number, int ttl, int blockempty, struct dundi_hint_metadata *hmd, int *expiration, int cbypass, int modeselect, dundi_eid *skip, dundi_eid *avoid[], int direct[]) { int res; struct dundi_request dr, *pending; dundi_eid *rooteid=NULL; int x; int ttlms; int ms; int foundcache; int skipped=0; int order=0; char eid_str[20]; struct timeval start; /* Don't do anthing for a hungup channel */ if (chan && ast_check_hangup(chan)) return 0; ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME; for (x=0;avoid[x];x++) rooteid = avoid[x]; /* Now perform real check */ memset(&dr, 0, sizeof(dr)); if (pipe(dr.pfds)) { ast_log(LOG_WARNING, "pipe failed: %s\n" , strerror(errno)); return -1; } dr.dr = result; dr.hmd = hmd; dr.maxcount = maxret; dr.expiration = *expiration; dr.cbypass = cbypass; dr.crc32 = avoid_crc32(avoid); ast_copy_string(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext)); ast_copy_string(dr.number, number, sizeof(dr.number)); if (rooteid) dr.root_eid = *rooteid; res = register_request(&dr, &pending); if (res) { /* Already a request */ if (rooteid && !ast_eid_cmp(&dr.root_eid, &pending->root_eid)) { /* This is on behalf of someone else. Go ahead and close this out since they'll get their answer anyway. */ ast_debug(1, "Oooh, duplicate request for '%s@%s' for '%s'\n", dr.number,dr.dcontext,ast_eid_to_str(eid_str, sizeof(eid_str), &dr.root_eid)); close(dr.pfds[0]); close(dr.pfds[1]); return -2; } else { /* Wait for the cache to populate */ ast_debug(1, "Waiting for similar request for '%s@%s' for '%s'\n", dr.number,dr.dcontext,ast_eid_to_str(eid_str, sizeof(eid_str), &pending->root_eid)); start = ast_tvnow(); while(check_request(pending) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !ast_check_hangup(chan))) { /* XXX Would be nice to have a way to poll/select here XXX */ /* XXX this is a busy wait loop!!! */ usleep(1); } /* Continue on as normal, our cache should kick in */ } } /* Create transactions */ do { order = skipped; skipped = 0; foundcache = 0; build_transactions(&dr, ttl, order, &foundcache, &skipped, blockempty, cbypass, modeselect, skip, avoid, direct); } while (skipped && !foundcache && AST_LIST_EMPTY(&dr.trans)); /* If no TTL, abort and return 0 now after setting TTL expired hint. Couldn't do this earlier because we didn't know if we were going to have transactions or not. */ if (!ttl) { ast_set_flag_nonstd(hmd, DUNDI_HINT_TTL_EXPIRED); abort_request(&dr); unregister_request(&dr); close(dr.pfds[0]); close(dr.pfds[1]); return 0; } /* Optimize transactions */ optimize_transactions(&dr, order); /* Actually perform transactions */ discover_transactions(&dr); /* Wait for transaction to come back */ start = ast_tvnow(); while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !ast_check_hangup(chan))) { ms = 100; ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL); } if (chan && ast_check_hangup(chan)) ast_debug(1, "Hrm, '%s' hungup before their query for %s@%s finished\n", chan->name, dr.number, dr.dcontext); cancel_request(&dr); unregister_request(&dr); res = dr.respcount; *expiration = dr.expiration; close(dr.pfds[0]); close(dr.pfds[1]); return res; } int dundi_lookup(struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number, int cbypass) { struct dundi_hint_metadata hmd; dundi_eid *avoid[1] = { NULL, }; int direct[1] = { 0, }; int expiration = dundi_cache_time; memset(&hmd, 0, sizeof(hmd)); hmd.flags = DUNDI_HINT_DONT_ASK | DUNDI_HINT_UNAFFECTED; return dundi_lookup_internal(result, maxret, chan, dcontext, number, dundi_ttl, 0, &hmd, &expiration, cbypass, 0, NULL, avoid, direct); } static void reschedule_precache(const char *number, const char *context, int expiration) { int len; struct dundi_precache_queue *qe, *prev; AST_LIST_LOCK(&pcq); AST_LIST_TRAVERSE_SAFE_BEGIN(&pcq, qe, list) { if (!strcmp(number, qe->number) && !strcasecmp(context, qe->context)) { AST_LIST_REMOVE_CURRENT(list); break; } } AST_LIST_TRAVERSE_SAFE_END; if (!qe) { len = sizeof(*qe); len += strlen(number) + 1; len += strlen(context) + 1; if (!(qe = ast_calloc(1, len))) { AST_LIST_UNLOCK(&pcq); return; } strcpy(qe->number, number); qe->context = qe->number + strlen(number) + 1; strcpy(qe->context, context); } time(&qe->expiration); qe->expiration += expiration; if ((prev = AST_LIST_FIRST(&pcq))) { while (AST_LIST_NEXT(prev, list) && ((AST_LIST_NEXT(prev, list))->expiration <= qe->expiration)) prev = AST_LIST_NEXT(prev, list); AST_LIST_INSERT_AFTER(&pcq, prev, qe, list); } else AST_LIST_INSERT_HEAD(&pcq, qe, list); AST_LIST_UNLOCK(&pcq); } static void dundi_precache_full(void) { struct dundi_mapping *cur; struct ast_context *con; struct ast_exten *e; AST_LIST_TRAVERSE(&mappings, cur, list) { ast_log(LOG_NOTICE, "Should precache context '%s'\n", cur->dcontext); ast_rdlock_contexts(); con = NULL; while ((con = ast_walk_contexts(con))) { if (strcasecmp(cur->lcontext, ast_get_context_name(con))) continue; /* Found the match, now queue them all up */ ast_rdlock_context(con); e = NULL; while ((e = ast_walk_context_extensions(con, e))) reschedule_precache(ast_get_extension_name(e), cur->dcontext, 0); ast_unlock_context(con); } ast_unlock_contexts(); } } static int dundi_precache_internal(const char *context, const char *number, int ttl, dundi_eid *avoids[]) { struct dundi_request dr; struct dundi_hint_metadata hmd; struct dundi_result dr2[MAX_RESULTS]; struct timeval start; struct dundi_mapping *maps = NULL, *cur; int nummaps = 0; int foundanswers; int foundcache, skipped, ttlms, ms; if (!context) context = "e164"; ast_debug(1, "Precache internal (%s@%s)!\n", number, context); AST_LIST_LOCK(&peers); AST_LIST_TRAVERSE(&mappings, cur, list) { if (!strcasecmp(cur->dcontext, context)) nummaps++; } if (nummaps) { maps = alloca(nummaps * sizeof(*maps)); nummaps = 0; if (maps) { AST_LIST_TRAVERSE(&mappings, cur, list) { if (!strcasecmp(cur->dcontext, context)) maps[nummaps++] = *cur; } } } AST_LIST_UNLOCK(&peers); if (!nummaps || !maps) return -1; ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME; memset(&dr2, 0, sizeof(dr2)); memset(&dr, 0, sizeof(dr)); memset(&hmd, 0, sizeof(hmd)); dr.dr = dr2; ast_copy_string(dr.number, number, sizeof(dr.number)); ast_copy_string(dr.dcontext, context ? context : "e164", sizeof(dr.dcontext)); dr.maxcount = MAX_RESULTS; dr.expiration = dundi_cache_time; dr.hmd = &hmd; dr.pfds[0] = dr.pfds[1] = -1; if (pipe(dr.pfds) < 0) { ast_log(LOG_WARNING, "pipe() failed: %s\n", strerror(errno)); return -1; } build_transactions(&dr, ttl, 0, &foundcache, &skipped, 0, 1, 1, NULL, avoids, NULL); optimize_transactions(&dr, 0); foundanswers = 0; precache_transactions(&dr, maps, nummaps, &dr.expiration, &foundanswers); if (foundanswers) { if (dr.expiration > 0) reschedule_precache(dr.number, dr.dcontext, dr.expiration); else ast_log(LOG_NOTICE, "Weird, expiration = %d, but need to precache for %s@%s?!\n", dr.expiration, dr.number, dr.dcontext); } start = ast_tvnow(); while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms)) { if (dr.pfds[0] > -1) { ms = 100; ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL); } else usleep(1); } cancel_request(&dr); if (dr.pfds[0] > -1) { close(dr.pfds[0]); close(dr.pfds[1]); } return 0; } int dundi_precache(const char *context, const char *number) { dundi_eid *avoid[1] = { NULL, }; return dundi_precache_internal(context, number, dundi_ttl, avoid); } static int dundi_query_eid_internal(struct dundi_entity_info *dei, const char *dcontext, dundi_eid *eid, struct dundi_hint_metadata *hmd, int ttl, int blockempty, dundi_eid *avoid[]) { int res; struct dundi_request dr; dundi_eid *rooteid=NULL; int x; int ttlms; int skipped=0; int foundcache=0; struct timeval start; ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME; for (x=0;avoid[x];x++) rooteid = avoid[x]; /* Now perform real check */ memset(&dr, 0, sizeof(dr)); dr.hmd = hmd; dr.dei = dei; dr.pfds[0] = dr.pfds[1] = -1; ast_copy_string(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext)); memcpy(&dr.query_eid, eid, sizeof(dr.query_eid)); if (rooteid) dr.root_eid = *rooteid; /* Create transactions */ build_transactions(&dr, ttl, 9999, &foundcache, &skipped, blockempty, 0, 0, NULL, avoid, NULL); /* If no TTL, abort and return 0 now after setting TTL expired hint. Couldn't do this earlier because we didn't know if we were going to have transactions or not. */ if (!ttl) { ast_set_flag_nonstd(hmd, DUNDI_HINT_TTL_EXPIRED); return 0; } /* Optimize transactions */ optimize_transactions(&dr, 9999); /* Actually perform transactions */ query_transactions(&dr); /* Wait for transaction to come back */ start = ast_tvnow(); while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms)) usleep(1); res = dr.respcount; return res; } int dundi_query_eid(struct dundi_entity_info *dei, const char *dcontext, dundi_eid eid) { dundi_eid *avoid[1] = { NULL, }; struct dundi_hint_metadata hmd; memset(&hmd, 0, sizeof(hmd)); return dundi_query_eid_internal(dei, dcontext, &eid, &hmd, dundi_ttl, 0, avoid); } static int dundifunc_read(struct ast_channel *chan, const char *cmd, char *num, char *buf, size_t len) { char *context; char *opts; int results; int x; int bypass = 0; struct ast_module_user *u; struct dundi_result dr[MAX_RESULTS]; buf[0] = '\0'; if (ast_strlen_zero(num)) { ast_log(LOG_WARNING, "DUNDILOOKUP requires an argument (number)\n"); return -1; } u = ast_module_user_add(chan); context = strchr(num, '|'); if (context) { *context++ = '\0'; opts = strchr(context, '|'); if (opts) { *opts++ = '\0'; if (strchr(opts, 'b')) bypass = 1; } } if (ast_strlen_zero(context)) context = "e164"; results = dundi_lookup(dr, MAX_RESULTS, NULL, context, num, bypass); if (results > 0) { sort_results(dr, results); for (x = 0; x < results; x++) { if (ast_test_flag(dr + x, DUNDI_FLAG_EXISTS)) { snprintf(buf, len, "%s/%s", dr[x].tech, dr[x].dest); break; } } } ast_module_user_remove(u); return 0; } /*! DUNDILOOKUP * \ingroup functions */ static struct ast_custom_function dundi_function = { .name = "DUNDILOOKUP", .synopsis = "Do a DUNDi lookup of a phone number.", .syntax = "DUNDILOOKUP(number[|context[|options]])", .desc = "This will do a DUNDi lookup of the given phone number.\n" "If no context is given, the default will be e164. The result of\n" "this function will return the Technology/Resource found in the first result\n" "in the DUNDi lookup. If no results were found, the result will be blank.\n" "If the 'b' option is specified, the internal DUNDi cache will\n" "be bypassed.\n", .read = dundifunc_read, }; enum { OPT_BYPASS_CACHE = (1 << 0), }; AST_APP_OPTIONS(dundi_query_opts, BEGIN_OPTIONS AST_APP_OPTION('b', OPT_BYPASS_CACHE), END_OPTIONS ); unsigned int dundi_result_id; struct dundi_result_datastore { struct dundi_result results[MAX_RESULTS]; unsigned int num_results; unsigned int id; }; static void drds_destroy(struct dundi_result_datastore *drds) { ast_free(drds); } static void drds_destroy_cb(void *data) { struct dundi_result_datastore *drds = data; drds_destroy(drds); } static const struct ast_datastore_info dundi_result_datastore_info = { .type = "DUNDIQUERY", .destroy = drds_destroy_cb, }; static int dundi_query_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) { struct ast_module_user *u; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(number); AST_APP_ARG(context); AST_APP_ARG(options); ); struct ast_flags opts = { 0, }; char *parse; struct dundi_result_datastore *drds; struct ast_datastore *datastore; u = ast_module_user_add(chan); if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "DUNDIQUERY requires an argument (number)\n"); ast_module_user_remove(u); return -1; } if (!chan) { ast_log(LOG_ERROR, "DUNDIQUERY can not be used without a channel!\n"); ast_module_user_remove(u); return -1; } parse = ast_strdupa(data); AST_STANDARD_APP_ARGS(args, parse); if (!ast_strlen_zero(args.options)) ast_app_parse_options(dundi_query_opts, &opts, NULL, args.options); if (ast_strlen_zero(args.context)) args.context = "e164"; if (!(drds = ast_calloc(1, sizeof(*drds)))) { ast_module_user_remove(u); return -1; } drds->id = ast_atomic_fetchadd_int((int *) &dundi_result_id, 1); snprintf(buf, len, "%u", drds->id); if (!(datastore = ast_datastore_alloc(&dundi_result_datastore_info, buf))) { drds_destroy(drds); ast_module_user_remove(u); return -1; } datastore->data = drds; drds->num_results = dundi_lookup(drds->results, ARRAY_LEN(drds->results), NULL, args.context, args.number, ast_test_flag(&opts, OPT_BYPASS_CACHE)); if (drds->num_results > 0) sort_results(drds->results, drds->num_results); ast_channel_lock(chan); ast_channel_datastore_add(chan, datastore); ast_channel_unlock(chan); ast_module_user_remove(u); return 0; } static struct ast_custom_function dundi_query_function = { .name = "DUNDIQUERY", .synopsis = "Initiate a DUNDi query.", .syntax = "DUNDIQUERY(number[|context[|options]])", .desc = "This will do a DUNDi lookup of the given phone number.\n" "If no context is given, the default will be e164. The result of\n" "this function will be a numeric ID that can be used to retrieve\n" "the results with the DUNDIRESULT function. If the 'b' option is\n" "is specified, the internal DUNDi cache will be bypassed.\n", .read = dundi_query_read, }; static int dundi_result_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) { struct ast_module_user *u; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(id); AST_APP_ARG(resultnum); ); char *parse; unsigned int num; struct dundi_result_datastore *drds; struct ast_datastore *datastore; int res = -1; u = ast_module_user_add(chan); if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "DUNDIRESULT requires an argument (id and resultnum)\n"); goto finish; } if (!chan) { ast_log(LOG_ERROR, "DUNDRESULT can not be used without a channel!\n"); goto finish; } parse = ast_strdupa(data); AST_STANDARD_APP_ARGS(args, parse); if (ast_strlen_zero(args.id)) { ast_log(LOG_ERROR, "A result ID must be provided to DUNDIRESULT\n"); goto finish; } if (ast_strlen_zero(args.resultnum)) { ast_log(LOG_ERROR, "A result number must be given to DUNDIRESULT!\n"); goto finish; } ast_channel_lock(chan); datastore = ast_channel_datastore_find(chan, &dundi_result_datastore_info, args.id); ast_channel_unlock(chan); if (!datastore) { ast_log(LOG_WARNING, "No DUNDi results found for query ID '%s'\n", args.id); goto finish; } drds = datastore->data; if (!strcasecmp(args.resultnum, "getnum")) { snprintf(buf, len, "%u", drds->num_results); res = 0; goto finish; } if (sscanf(args.resultnum, "%u", &num) != 1) { ast_log(LOG_ERROR, "Invalid value '%s' for resultnum to DUNDIRESULT!\n", args.resultnum); goto finish; } if (num && num <= drds->num_results) { snprintf(buf, len, "%s/%s", drds->results[num - 1].tech, drds->results[num - 1].dest); res = 0; } else ast_log(LOG_WARNING, "Result number %u is not valid for DUNDi query results for ID %s!\n", num, args.id); finish: ast_module_user_remove(u); return res; } static struct ast_custom_function dundi_result_function = { .name = "DUNDIRESULT", .synopsis = "Retrieve results from a DUNDIQUERY", .syntax = "DUNDIRESULT(id|resultnum)", .desc = "This function will retrieve results from a previous use\n" "of the DUNDIQUERY function.\n" " id - This argument is the identifier returned by the DUNDIQUERY function.\n" " resultnum - This is the number of the result that you want to retrieve.\n" " Results start at 1. If this argument is specified as \"getnum\",\n" " then it will return the total number of results that are available.\n", .read = dundi_result_read, }; static void mark_peers(void) { struct dundi_peer *peer; AST_LIST_LOCK(&peers); AST_LIST_TRAVERSE(&peers, peer, list) { peer->dead = 1; } AST_LIST_UNLOCK(&peers); } static void mark_mappings(void) { struct dundi_mapping *map; AST_LIST_LOCK(&peers); AST_LIST_TRAVERSE(&mappings, map, list) { map->dead = 1; } AST_LIST_UNLOCK(&peers); } static void destroy_permissions(struct permissionlist *permlist) { struct permission *perm; while ((perm = AST_LIST_REMOVE_HEAD(permlist, list))) ast_free(perm); } static void destroy_peer(struct dundi_peer *peer) { AST_SCHED_DEL(sched, peer->registerid); if (peer->regtrans) destroy_trans(peer->regtrans, 0); AST_SCHED_DEL(sched, peer->qualifyid); destroy_permissions(&peer->permit); destroy_permissions(&peer->include); ast_free(peer); } static void destroy_map(struct dundi_mapping *map) { if (map->weightstr) ast_free(map->weightstr); ast_free(map); } static void prune_peers(void) { struct dundi_peer *peer; AST_LIST_LOCK(&peers); AST_LIST_TRAVERSE_SAFE_BEGIN(&peers, peer, list) { if (peer->dead) { AST_LIST_REMOVE_CURRENT(list); destroy_peer(peer); } } AST_LIST_TRAVERSE_SAFE_END; AST_LIST_UNLOCK(&peers); } static void prune_mappings(void) { struct dundi_mapping *map; AST_LIST_LOCK(&peers); AST_LIST_TRAVERSE_SAFE_BEGIN(&mappings, map, list) { if (map->dead) { AST_LIST_REMOVE_CURRENT(list); destroy_map(map); } } AST_LIST_TRAVERSE_SAFE_END; AST_LIST_UNLOCK(&peers); } static void append_permission(struct permissionlist *permlist, const char *s, int allow) { struct permission *perm; if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(s) + 1))) return; strcpy(perm->name, s); perm->allow = allow; AST_LIST_INSERT_TAIL(permlist, perm, list); } #define MAX_OPTS 128 static void build_mapping(const char *name, const char *value) { char *t, *fields[MAX_OPTS]; struct dundi_mapping *map; int x; int y; t = ast_strdupa(value); AST_LIST_TRAVERSE(&mappings, map, list) { /* Find a double match */ if (!strcasecmp(map->dcontext, name) && (!strncasecmp(map->lcontext, value, strlen(map->lcontext)) && (!value[strlen(map->lcontext)] || (value[strlen(map->lcontext)] == ',')))) break; } if (!map) { if (!(map = ast_calloc(1, sizeof(*map)))) return; AST_LIST_INSERT_HEAD(&mappings, map, list); map->dead = 1; } map->options = 0; memset(fields, 0, sizeof(fields)); x = 0; while (t && x < MAX_OPTS) { fields[x++] = t; t = strchr(t, ','); if (t) { *t = '\0'; t++; } } /* Russell was here, arrrr! */ if ((x == 1) && ast_strlen_zero(fields[0])) { /* Placeholder mapping */ ast_copy_string(map->dcontext, name, sizeof(map->dcontext)); map->dead = 0; } else if (x >= 4) { ast_copy_string(map->dcontext, name, sizeof(map->dcontext)); ast_copy_string(map->lcontext, fields[0], sizeof(map->lcontext)); if ((sscanf(fields[1], "%d", &map->_weight) == 1) && (map->_weight >= 0) && (map->_weight <= MAX_WEIGHT)) { ast_copy_string(map->dest, fields[3], sizeof(map->dest)); if ((map->tech = str2tech(fields[2]))) map->dead = 0; } else if (!strncmp(fields[1], "${", 2) && fields[1][strlen(fields[1]) - 1] == '}') { map->weightstr = ast_strdup(fields[1]); ast_copy_string(map->dest, fields[3], sizeof(map->dest)); if ((map->tech = str2tech(fields[2]))) map->dead = 0; } else { ast_log(LOG_WARNING, "Invalid weight '%s' specified, deleting entry '%s/%s'\n", fields[1], map->dcontext, map->lcontext); } for (y = 4;y < x; y++) { if (!strcasecmp(fields[y], "nounsolicited")) map->options |= DUNDI_FLAG_NOUNSOLICITED; else if (!strcasecmp(fields[y], "nocomunsolicit")) map->options |= DUNDI_FLAG_NOCOMUNSOLICIT; else if (!strcasecmp(fields[y], "residential")) map->options |= DUNDI_FLAG_RESIDENTIAL; else if (!strcasecmp(fields[y], "commercial")) map->options |= DUNDI_FLAG_COMMERCIAL; else if (!strcasecmp(fields[y], "mobile")) map->options |= DUNDI_FLAG_MOBILE; else if (!strcasecmp(fields[y], "nopartial")) map->options |= DUNDI_FLAG_INTERNAL_NOPARTIAL; else ast_log(LOG_WARNING, "Don't know anything about option '%s'\n", fields[y]); } } else ast_log(LOG_WARNING, "Expected at least %d arguments in map, but got only %d\n", 4, x); } /* \note Called with the peers list already locked */ static int do_register(const void *data) { struct dundi_ie_data ied; struct dundi_peer *peer = (struct dundi_peer *)data; char eid_str[20]; char eid_str2[20]; ast_debug(1, "Register us as '%s' to '%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->us_eid), ast_eid_to_str(eid_str2, sizeof(eid_str2), &peer->eid)); peer->registerid = ast_sched_add(sched, default_expiration * 1000, do_register, data); /* Destroy old transaction if there is one */ if (peer->regtrans) destroy_trans(peer->regtrans, 0); peer->regtrans = create_transaction(peer); if (peer->regtrans) { ast_set_flag(peer->regtrans, FLAG_ISREG); memset(&ied, 0, sizeof(ied)); dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION); dundi_ie_append_eid(&ied, DUNDI_IE_EID, &peer->regtrans->us_eid); dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, default_expiration); dundi_send(peer->regtrans, DUNDI_COMMAND_REGREQ, 0, 0, &ied); } else ast_log(LOG_NOTICE, "Unable to create new transaction for registering to '%s'!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); return 0; } static int do_qualify(const void *data) { struct dundi_peer *peer = (struct dundi_peer *)data; peer->qualifyid = -1; qualify_peer(peer, 0); return 0; } static void qualify_peer(struct dundi_peer *peer, int schedonly) { int when; AST_SCHED_DEL(sched, peer->qualifyid); if (peer->qualtrans) destroy_trans(peer->qualtrans, 0); peer->qualtrans = NULL; if (peer->maxms > 0) { when = 60000; if (peer->lastms < 0) when = 10000; if (schedonly) when = 5000; peer->qualifyid = ast_sched_add(sched, when, do_qualify, peer); if (!schedonly) peer->qualtrans = create_transaction(peer); if (peer->qualtrans) { peer->qualtx = ast_tvnow(); ast_set_flag(peer->qualtrans, FLAG_ISQUAL); dundi_send(peer->qualtrans, DUNDI_COMMAND_NULL, 0, 1, NULL); } } } static void populate_addr(struct dundi_peer *peer, dundi_eid *eid) { char data[256]; char *c; int port, expire; char eid_str[20]; ast_eid_to_str(eid_str, sizeof(eid_str), eid); if (!ast_db_get("dundi/dpeers", eid_str, data, sizeof(data))) { c = strchr(data, ':'); if (c) { *c = '\0'; c++; if (sscanf(c, "%d:%d", &port, &expire) == 2) { /* Got it! */ inet_aton(data, &peer->addr.sin_addr); peer->addr.sin_family = AF_INET; peer->addr.sin_port = htons(port); peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer); } } } } static void build_peer(dundi_eid *eid, struct ast_variable *v, int *globalpcmode) { struct dundi_peer *peer; struct ast_hostent he; struct hostent *hp; dundi_eid testeid; int needregister=0; char eid_str[20]; AST_LIST_LOCK(&peers); AST_LIST_TRAVERSE(&peers, peer, list) { if (!ast_eid_cmp(&peer->eid, eid)) { break; } } if (!peer) { /* Add us into the list */ if (!(peer = ast_calloc(1, sizeof(*peer)))) { AST_LIST_UNLOCK(&peers); return; } peer->registerid = -1; peer->registerexpire = -1; peer->qualifyid = -1; peer->addr.sin_family = AF_INET; peer->addr.sin_port = htons(DUNDI_PORT); populate_addr(peer, eid); AST_LIST_INSERT_HEAD(&peers, peer, list); } peer->dead = 0; peer->eid = *eid; peer->us_eid = global_eid; destroy_permissions(&peer->permit); destroy_permissions(&peer->include); AST_SCHED_DEL(sched, peer->registerid); for (; v; v = v->next) { if (!strcasecmp(v->name, "inkey")) { ast_copy_string(peer->inkey, v->value, sizeof(peer->inkey)); } else if (!strcasecmp(v->name, "outkey")) { ast_copy_string(peer->outkey, v->value, sizeof(peer->outkey)); } else if (!strcasecmp(v->name, "host")) { if (!strcasecmp(v->value, "dynamic")) { peer->dynamic = 1; } else { hp = ast_gethostbyname(v->value, &he); if (hp) { memcpy(&peer->addr.sin_addr, hp->h_addr, sizeof(peer->addr.sin_addr)); peer->dynamic = 0; } else { ast_log(LOG_WARNING, "Unable to find host '%s' at line %d\n", v->value, v->lineno); peer->dead = 1; } } } else if (!strcasecmp(v->name, "ustothem")) { if (!ast_str_to_eid(&testeid, v->value)) peer->us_eid = testeid; else ast_log(LOG_WARNING, "'%s' is not a valid DUNDi Entity Identifier at line %d\n", v->value, v->lineno); } else if (!strcasecmp(v->name, "include")) { append_permission(&peer->include, v->value, 1); } else if (!strcasecmp(v->name, "permit")) { append_permission(&peer->permit, v->value, 1); } else if (!strcasecmp(v->name, "noinclude")) { append_permission(&peer->include, v->value, 0); } else if (!strcasecmp(v->name, "deny")) { append_permission(&peer->permit, v->value, 0); } else if (!strcasecmp(v->name, "register")) { needregister = ast_true(v->value); } else if (!strcasecmp(v->name, "order")) { if (!strcasecmp(v->value, "primary")) peer->order = 0; else if (!strcasecmp(v->value, "secondary")) peer->order = 1; else if (!strcasecmp(v->value, "tertiary")) peer->order = 2; else if (!strcasecmp(v->value, "quartiary")) peer->order = 3; else { ast_log(LOG_WARNING, "'%s' is not a valid order, should be primary, secondary, tertiary or quartiary at line %d\n", v->value, v->lineno); } } else if (!strcasecmp(v->name, "qualify")) { if (!strcasecmp(v->value, "no")) { peer->maxms = 0; } else if (!strcasecmp(v->value, "yes")) { peer->maxms = DEFAULT_MAXMS; } else if (sscanf(v->value, "%d", &peer->maxms) != 1) { ast_log(LOG_WARNING, "Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of dundi.conf\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), v->lineno); peer->maxms = 0; } } else if (!strcasecmp(v->name, "model")) { if (!strcasecmp(v->value, "inbound")) peer->model = DUNDI_MODEL_INBOUND; else if (!strcasecmp(v->value, "outbound")) peer->model = DUNDI_MODEL_OUTBOUND; else if (!strcasecmp(v->value, "symmetric")) peer->model = DUNDI_MODEL_SYMMETRIC; else if (!strcasecmp(v->value, "none")) peer->model = 0; else { ast_log(LOG_WARNING, "Unknown model '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n", v->value, v->lineno); } } else if (!strcasecmp(v->name, "precache")) { if (!strcasecmp(v->value, "inbound")) peer->pcmodel = DUNDI_MODEL_INBOUND; else if (!strcasecmp(v->value, "outbound")) peer->pcmodel = DUNDI_MODEL_OUTBOUND; else if (!strcasecmp(v->value, "symmetric")) peer->pcmodel = DUNDI_MODEL_SYMMETRIC; else if (!strcasecmp(v->value, "none")) peer->pcmodel = 0; else { ast_log(LOG_WARNING, "Unknown pcmodel '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n", v->value, v->lineno); } } } (*globalpcmode) |= peer->pcmodel; if (!peer->model && !peer->pcmodel) { ast_log(LOG_WARNING, "Peer '%s' lacks a model or pcmodel, discarding!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); peer->dead = 1; } else if ((peer->model & DUNDI_MODEL_INBOUND) && (peer->pcmodel & DUNDI_MODEL_OUTBOUND)) { ast_log(LOG_WARNING, "Peer '%s' may not be both inbound/symmetric model and outbound/symmetric precache model, discarding!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); peer->dead = 1; } else if ((peer->model & DUNDI_MODEL_OUTBOUND) && (peer->pcmodel & DUNDI_MODEL_INBOUND)) { ast_log(LOG_WARNING, "Peer '%s' may not be both outbound/symmetric model and inbound/symmetric precache model, discarding!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); peer->dead = 1; } else if (!AST_LIST_EMPTY(&peer->include) && !(peer->model & DUNDI_MODEL_OUTBOUND) && !(peer->pcmodel & DUNDI_MODEL_INBOUND)) { ast_log(LOG_WARNING, "Peer '%s' is supposed to be included in outbound searches but isn't an outbound peer or inbound precache!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); } else if (!AST_LIST_EMPTY(&peer->permit) && !(peer->model & DUNDI_MODEL_INBOUND) && !(peer->pcmodel & DUNDI_MODEL_OUTBOUND)) { ast_log(LOG_WARNING, "Peer '%s' is supposed to have permission for some inbound searches but isn't an inbound peer or outbound precache!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid)); } else { if (needregister) { peer->registerid = ast_sched_add(sched, 2000, do_register, peer); } qualify_peer(peer, 1); } AST_LIST_UNLOCK(&peers); } static int dundi_helper(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *data, int flag) { struct dundi_result results[MAX_RESULTS]; int res; int x; int found = 0; if (!strncasecmp(context, "macro-", 6)) { if (!chan) { ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n"); return -1; } /* If done as a macro, use macro extension */ if (!strcasecmp(exten, "s")) { exten = pbx_builtin_getvar_helper(chan, "ARG1"); if (ast_strlen_zero(exten)) exten = chan->macroexten; if (ast_strlen_zero(exten)) exten = chan->exten; if (ast_strlen_zero(exten)) { ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n"); return -1; } } if (ast_strlen_zero(data)) data = "e164"; } else { if (ast_strlen_zero(data)) data = context; } res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0); for (x=0;x= priority) return 1; return 0; } static int dundi_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) { return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_EXISTS); } static int dundi_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) { return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_CANMATCH); } static int dundi_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) { struct dundi_result results[MAX_RESULTS]; int res; int x=0; char req[1024]; const char *dundiargs; struct ast_app *dial; if (!strncasecmp(context, "macro-", 6)) { if (!chan) { ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n"); return -1; } /* If done as a macro, use macro extension */ if (!strcasecmp(exten, "s")) { exten = pbx_builtin_getvar_helper(chan, "ARG1"); if (ast_strlen_zero(exten)) exten = chan->macroexten; if (ast_strlen_zero(exten)) exten = chan->exten; if (ast_strlen_zero(exten)) { ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n"); return -1; } } if (ast_strlen_zero(data)) data = "e164"; } else { if (ast_strlen_zero(data)) data = context; } res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0); if (res > 0) { sort_results(results, res); for (x=0;xh_addr, sizeof(sin2.sin_addr)); ast_copy_string(ipaddr, ast_inet_ntoa(sin2.sin_addr), sizeof(ipaddr)); } else ast_log(LOG_WARNING, "Unable to look up host '%s'\n", hn); } else ast_log(LOG_WARNING, "Unable to get host name!\n"); AST_LIST_LOCK(&peers); memcpy(&global_eid, &ast_eid_default, sizeof(global_eid)); global_storehistory = 0; ast_copy_string(secretpath, "dundi", sizeof(secretpath)); v = ast_variable_browse(cfg, "general"); while(v) { if (!strcasecmp(v->name, "port")){ sin->sin_port = ntohs(atoi(v->value)); if(last_port==0){ last_port=sin->sin_port; } else if(sin->sin_port != last_port) ast_log(LOG_WARNING, "change to port ignored until next asterisk re-start\n"); } else if (!strcasecmp(v->name, "bindaddr")) { struct hostent *hep; struct ast_hostent hent; hep = ast_gethostbyname(v->value, &hent); if (hep) { memcpy(&sin->sin_addr, hep->h_addr, sizeof(sin->sin_addr)); } else ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value); } else if (!strcasecmp(v->name, "authdebug")) { authdebug = ast_true(v->value); } else if (!strcasecmp(v->name, "ttl")) { if ((sscanf(v->value, "%d", &x) == 1) && (x > 0) && (x < DUNDI_DEFAULT_TTL)) { dundi_ttl = x; } else { ast_log(LOG_WARNING, "'%s' is not a valid TTL at line %d, must be number from 1 to %d\n", v->value, v->lineno, DUNDI_DEFAULT_TTL); } } else if (!strcasecmp(v->name, "autokill")) { if (sscanf(v->value, "%d", &x) == 1) { if (x >= 0) global_autokilltimeout = x; else ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno); } else if (ast_true(v->value)) { global_autokilltimeout = DEFAULT_MAXMS; } else { global_autokilltimeout = 0; } } else if (!strcasecmp(v->name, "entityid")) { if (!ast_str_to_eid(&testeid, v->value)) global_eid = testeid; else ast_log(LOG_WARNING, "Invalid global endpoint identifier '%s' at line %d\n", v->value, v->lineno); } else if (!strcasecmp(v->name, "tos")) { if (ast_str2tos(v->value, &tos)) ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno); } else if (!strcasecmp(v->name, "department")) { ast_copy_string(dept, v->value, sizeof(dept)); } else if (!strcasecmp(v->name, "organization")) { ast_copy_string(org, v->value, sizeof(org)); } else if (!strcasecmp(v->name, "locality")) { ast_copy_string(locality, v->value, sizeof(locality)); } else if (!strcasecmp(v->name, "stateprov")) { ast_copy_string(stateprov, v->value, sizeof(stateprov)); } else if (!strcasecmp(v->name, "country")) { ast_copy_string(country, v->value, sizeof(country)); } else if (!strcasecmp(v->name, "email")) { ast_copy_string(email, v->value, sizeof(email)); } else if (!strcasecmp(v->name, "phone")) { ast_copy_string(phone, v->value, sizeof(phone)); } else if (!strcasecmp(v->name, "storehistory")) { global_storehistory = ast_true(v->value); } else if (!strcasecmp(v->name, "cachetime")) { if ((sscanf(v->value, "%d", &x) == 1)) { dundi_cache_time = x; } else { ast_log(LOG_WARNING, "'%s' is not a valid cache time at line %d. Using default value '%d'.\n", v->value, v->lineno, DUNDI_DEFAULT_CACHE_TIME); } } v = v->next; } AST_LIST_UNLOCK(&peers); mark_mappings(); v = ast_variable_browse(cfg, "mappings"); while(v) { build_mapping(v->name, v->value); v = v->next; } prune_mappings(); mark_peers(); cat = ast_category_browse(cfg, NULL); while(cat) { if (strcasecmp(cat, "general") && strcasecmp(cat, "mappings")) { /* Entries */ if (!ast_str_to_eid(&testeid, cat)) build_peer(&testeid, ast_variable_browse(cfg, cat), &globalpcmodel); else if (!strcasecmp(cat, "*")) { build_peer(&empty_eid, ast_variable_browse(cfg, cat), &globalpcmodel); any_peer = find_peer(NULL); } else ast_log(LOG_NOTICE, "Ignoring invalid EID entry '%s'\n", cat); } cat = ast_category_browse(cfg, cat); } prune_peers(); ast_config_destroy(cfg); load_password(); if (globalpcmodel & DUNDI_MODEL_OUTBOUND) dundi_precache_full(); return 0; } static int unload_module(void) { pthread_t previous_netthreadid = netthreadid, previous_precachethreadid = precachethreadid, previous_clearcachethreadid = clearcachethreadid; ast_module_user_hangup_all(); /* Stop all currently running threads */ dundi_shutdown = 1; if (previous_netthreadid != AST_PTHREADT_NULL) { pthread_kill(previous_netthreadid, SIGURG); pthread_join(previous_netthreadid, NULL); } if (previous_precachethreadid != AST_PTHREADT_NULL) { pthread_kill(previous_precachethreadid, SIGURG); pthread_join(previous_precachethreadid, NULL); } if (previous_clearcachethreadid != AST_PTHREADT_NULL) { pthread_cancel(previous_clearcachethreadid); pthread_join(previous_clearcachethreadid, NULL); } ast_cli_unregister_multiple(cli_dundi, sizeof(cli_dundi) / sizeof(struct ast_cli_entry)); ast_unregister_switch(&dundi_switch); ast_custom_function_unregister(&dundi_function); ast_custom_function_unregister(&dundi_query_function); ast_custom_function_unregister(&dundi_result_function); close(netsocket); io_context_destroy(io); sched_context_destroy(sched); mark_mappings(); prune_mappings(); mark_peers(); prune_peers(); return 0; } static int reload(void) { struct sockaddr_in sin; if (set_config("dundi.conf", &sin, 1)) return AST_MODULE_LOAD_FAILURE; return AST_MODULE_LOAD_SUCCESS; } static int load_module(void) { struct sockaddr_in sin; dundi_set_output(dundi_debug_output); dundi_set_error(dundi_error_output); sin.sin_family = AF_INET; sin.sin_port = ntohs(DUNDI_PORT); sin.sin_addr.s_addr = INADDR_ANY; /* Make a UDP socket */ io = io_context_create(); sched = sched_context_create(); if (!io || !sched) return AST_MODULE_LOAD_FAILURE; if (set_config("dundi.conf", &sin, 0)) return AST_MODULE_LOAD_DECLINE; netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if (netsocket < 0) { ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno)); return AST_MODULE_LOAD_FAILURE; } if (bind(netsocket, (struct sockaddr *) &sin, sizeof(sin))) { ast_log(LOG_ERROR, "Unable to bind to %s port %d: %s\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), strerror(errno)); return AST_MODULE_LOAD_FAILURE; } ast_netsock_set_qos(netsocket, tos, 0, "DUNDi"); if (start_network_thread()) { ast_log(LOG_ERROR, "Unable to start network thread\n"); close(netsocket); return AST_MODULE_LOAD_FAILURE; } ast_cli_register_multiple(cli_dundi, sizeof(cli_dundi) / sizeof(*cli_dundi)); if (ast_register_switch(&dundi_switch)) ast_log(LOG_ERROR, "Unable to register DUNDi switch\n"); ast_custom_function_register(&dundi_function); ast_custom_function_register(&dundi_query_function); ast_custom_function_register(&dundi_result_function); ast_verb(2, "DUNDi Ready and Listening on %s port %d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); return AST_MODULE_LOAD_SUCCESS; } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Distributed Universal Number Discovery (DUNDi)", .load = load_module, .unload = unload_module, .reload = reload, ); asterisk-1.6.1.0/pbx/pbx_ael.c0000644000175000017500000002270711122537560015325 0ustar maniacmaniac/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 2006, Digium, Inc. * * Steve Murphy * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. */ /*! \file * * \brief Compile symbolic Asterisk Extension Logic into Asterisk extensions, version 2. * */ /*** MODULEINFO res_ael_share ***/ #include "asterisk.h" #if !defined(STANDALONE) ASTERISK_FILE_VERSION(__FILE__, "$Revision: 165794 $") #endif #include #include #include #ifdef STANDALONE #ifdef HAVE_MTX_PROFILE static int mtx_prof = -1; /* helps the standalone compile with the mtx_prof flag on */ #endif #endif #include "asterisk/pbx.h" #include "asterisk/config.h" #include "asterisk/module.h" #include "asterisk/logger.h" #include "asterisk/cli.h" #include "asterisk/app.h" #include "asterisk/callerid.h" #include "asterisk/hashtab.h" #include "asterisk/ael_structs.h" #include "asterisk/pval.h" #ifdef AAL_ARGCHECK #include "asterisk/argdesc.h" #endif /* these functions are in ../ast_expr2.fl */ #define DEBUG_READ (1 << 0) #define DEBUG_TOKENS (1 << 1) #define DEBUG_MACROS (1 << 2) #define DEBUG_CONTEXTS (1 << 3) static char *config = "extensions.ael"; static char *registrar = "pbx_ael"; static int pbx_load_module(void); #ifndef AAL_ARGCHECK /* for the time being, short circuit all the AAL related structures without permanently removing the code; after/during the AAL development, this code can be properly re-instated */ #endif #ifdef AAL_ARGCHECK int option_matches_j( struct argdesc *should, pval *is, struct argapp *app); int option_matches( struct argdesc *should, pval *is, struct argapp *app); int ael_is_funcname(char *name); #endif int check_app_args(pval *appcall, pval *arglist, struct argapp *app); void check_pval(pval *item, struct argapp *apps, int in_globals); void check_pval_item(pval *item, struct argapp *apps, int in_globals); void check_switch_expr(pval *item, struct argapp *apps); void ast_expr_register_extra_error_info(char *errmsg); void ast_expr_clear_extra_error_info(void); struct pval *find_macro(char *name); struct pval *find_context(char *name); struct pval *find_context(char *name); struct pval *find_macro(char *name); struct ael_priority *new_prio(void); struct ael_extension *new_exten(void); void destroy_extensions(struct ael_extension *exten); void set_priorities(struct ael_extension *exten); void add_extensions(struct ael_extension *exten); void ast_compile_ael2(struct ast_context **local_contexts, struct ast_hashtab *local_table, struct pval *root); void destroy_pval(pval *item); void destroy_pval_item(pval *item); int is_float(char *arg ); int is_int(char *arg ); int is_empty(char *arg); /* static void substitute_commas(char *str); */ static int aeldebug = 0; /* interface stuff */ /* if all the below are static, who cares if they are present? */ static int pbx_load_module(void) { int errs=0, sem_err=0, sem_warn=0, sem_note=0; char *rfilename; struct ast_context *local_contexts=NULL, *con; struct ast_hashtab *local_table=NULL; struct pval *parse_tree; ast_log(LOG_NOTICE, "Starting AEL load process.\n"); if (config[0] == '/') rfilename = (char *)config; else { rfilename = alloca(strlen(config) + strlen(ast_config_AST_CONFIG_DIR) + 2); sprintf(rfilename, "%s/%s", ast_config_AST_CONFIG_DIR, config); } if (access(rfilename,R_OK) != 0) { ast_log(LOG_NOTICE, "File %s not found; AEL declining load\n", rfilename); return AST_MODULE_LOAD_DECLINE; } parse_tree = ael2_parse(rfilename, &errs); ast_log(LOG_NOTICE, "AEL load process: parsed config file name '%s'.\n", rfilename); ael2_semantic_check(parse_tree, &sem_err, &sem_warn, &sem_note); if (errs == 0 && sem_err == 0) { ast_log(LOG_NOTICE, "AEL load process: checked config file name '%s'.\n", rfilename); local_table = ast_hashtab_create(11, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0); ast_compile_ael2(&local_contexts, local_table, parse_tree); ast_log(LOG_NOTICE, "AEL load process: compiled config file name '%s'.\n", rfilename); ast_merge_contexts_and_delete(&local_contexts, local_table, registrar); local_table = NULL; /* it's the dialplan global now */ local_contexts = NULL; ast_log(LOG_NOTICE, "AEL load process: merged config file name '%s'.\n", rfilename); for (con = ast_walk_contexts(NULL); con; con = ast_walk_contexts(con)) ast_context_verify_includes(con); ast_log(LOG_NOTICE, "AEL load process: verified config file name '%s'.\n", rfilename); } else { ast_log(LOG_ERROR, "Sorry, but %d syntax errors and %d semantic errors were detected. It doesn't make sense to compile.\n", errs, sem_err); destroy_pval(parse_tree); /* free up the memory */ return AST_MODULE_LOAD_DECLINE; } destroy_pval(parse_tree); /* free up the memory */ return AST_MODULE_LOAD_SUCCESS; } /* CLI interface */ static char *handle_cli_ael_debug_multiple_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { switch (cmd) { case CLI_INIT: e->command = "ael debug [read|tokens|macros|contexts|off]"; e->usage = "Usage: ael debug [read|tokens|macros|contexts|off]\n" " Enable AEL read, token, macro, or context debugging,\n" " or disable all AEL debugging messages. Note: this\n" " currently does nothing.\n"; return NULL; case CLI_GENERATE: return NULL; } if (a->argc != 3) return CLI_SHOWUSAGE; if (!strcasecmp(a->argv[2], "read")) aeldebug |= DEBUG_READ; else if (!strcasecmp(a->argv[2], "tokens")) aeldebug |= DEBUG_TOKENS; else if (!strcasecmp(a->argv[2], "macros")) aeldebug |= DEBUG_MACROS; else if (!strcasecmp(a->argv[2], "contexts")) aeldebug |= DEBUG_CONTEXTS; else if (!strcasecmp(a->argv[2], "off")) aeldebug = 0; else return CLI_SHOWUSAGE; return CLI_SUCCESS; } static char *handle_cli_ael_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { switch (cmd) { case CLI_INIT: e->command = "ael set debug {read|tokens|macros|contexts|off}"; e->usage = "Usage: ael set debug {read|tokens|macros|contexts|off}\n" " Enable AEL read, token, macro, or context debugging,\n" " or disable all AEL debugging messages. Note: this\n" " currently does nothing.\n"; return NULL; case CLI_GENERATE: return NULL; } if (a->argc != e->args) return CLI_SHOWUSAGE; if (!strcasecmp(a->argv[3], "read")) aeldebug |= DEBUG_READ; else if (!strcasecmp(a->argv[3], "tokens")) aeldebug |= DEBUG_TOKENS; else if (!strcasecmp(a->argv[3], "macros")) aeldebug |= DEBUG_MACROS; else if (!strcasecmp(a->argv[3], "contexts")) aeldebug |= DEBUG_CONTEXTS; else if (!strcasecmp(a->argv[3], "off")) aeldebug = 0; else return CLI_SHOWUSAGE; return CLI_SUCCESS; } static char *handle_cli_ael_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { switch (cmd) { case CLI_INIT: e->command = "ael reload"; e->usage = "Usage: ael reload\n" " Reloads AEL configuration.\n"; return NULL; case CLI_GENERATE: return NULL; } if (a->argc != 2) return CLI_SHOWUSAGE; return (pbx_load_module() ? CLI_FAILURE : CLI_SUCCESS); } static struct ast_cli_entry cli_ael_debug_multiple_deprecated = AST_CLI_DEFINE(handle_cli_ael_debug_multiple_deprecated, "Enable AEL debugging flags"); static struct ast_cli_entry cli_ael[] = { AST_CLI_DEFINE(handle_cli_ael_reload, "Reload AEL configuration"), AST_CLI_DEFINE(handle_cli_ael_set_debug, "Enable AEL debugging flags", .deprecate_cmd = &cli_ael_debug_multiple_deprecated) }; static int unload_module(void) { ast_context_destroy(NULL, registrar); ast_cli_unregister_multiple(cli_ael, sizeof(cli_ael) / sizeof(struct ast_cli_entry)); return 0; } static int load_module(void) { ast_cli_register_multiple(cli_ael, sizeof(cli_ael) / sizeof(struct ast_cli_entry)); return (pbx_load_module()); } static int reload(void) { return pbx_load_module(); } #ifdef STANDALONE #define AST_MODULE "ael" int ael_external_load_module(void); int ael_external_load_module(void) { pbx_load_module(); return 1; } #endif AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Asterisk Extension Language Compiler", .load = load_module, .unload = unload_module, .reload = reload, ); #ifdef AAL_ARGCHECK static char *ael_funclist[] = { "AGENT", "ARRAY", "BASE64_DECODE", "BASE64_ENCODE", "CALLERID", "CDR", "CHANNEL", "CHECKSIPDOMAIN", "CHECK_MD5", "CURL", "CUT", "DB", "DB_EXISTS", "DUNDILOOKUP", "ENUMLOOKUP", "ENV", "EVAL", "EXISTS", "FIELDQTY", "FILTER", "GROUP", "GROUP_COUNT", "GROUP_LIST", "GROUP_MATCH_COUNT", "IAXPEER", "IF", "IFTIME", "ISNULL", "KEYPADHASH", "LANGUAGE", "LEN", "MATH", "MD5", "MUSICCLASS", "QUEUEAGENTCOUNT", "QUEUE_MEMBER_COUNT", "QUEUE_MEMBER_LIST", "QUOTE", "RAND", "REGEX", "SET", "SHA1", "SIPCHANINFO", "SIPPEER", "SIP_HEADER", "SORT", "STAT", "STRFTIME", "STRPTIME", "TIMEOUT", "TXTCIDNAME", "URIDECODE", "URIENCODE", "VMCOUNT" }; int ael_is_funcname(char *name) { int s,t; t = sizeof(ael_funclist)/sizeof(char*); s = 0; while ((s < t) && strcasecmp(name, ael_funclist[s])) s++; if ( s < t ) return 1; else return 0; } #endif asterisk-1.6.1.0/pbx/pbx_lua.c0000644000175000017500000011144211103437035015333 0ustar maniacmaniac/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 1999 - 2007, Digium, Inc. * * Matthew Nicholson * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. */ /*! * \file * * \author Matthew Nicholson * \brief Lua PBX Switch * */ /*** MODULEINFO lua ***/ #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision: 153710 $") #include "asterisk/logger.h" #include "asterisk/channel.h" #include "asterisk/pbx.h" #include "asterisk/module.h" #include "asterisk/cli.h" #include "asterisk/utils.h" #include "asterisk/term.h" #include "asterisk/paths.h" #include "asterisk/hashtab.h" #include #include #include static char *config = "extensions.lua"; static char *registrar = "pbx_lua"; #define LUA_EXT_DATA_SIZE 256 #define LUA_BUF_SIZE 4096 static char *lua_read_extensions_file(lua_State *L, long *size); static int lua_load_extensions(lua_State *L, struct ast_channel *chan); static int lua_reload_extensions(lua_State *L); static void lua_free_extensions(void); static int lua_sort_extensions(lua_State *L); static int lua_register_switches(lua_State *L); static int lua_extension_cmp(lua_State *L); static int lua_find_extension(lua_State *L, const char *context, const char *exten, int priority, ast_switch_f *func, int push_func); static int lua_pbx_findapp(lua_State *L); static int lua_pbx_exec(lua_State *L); static int lua_get_variable_value(lua_State *L); static int lua_set_variable_value(lua_State *L); static int lua_get_variable(lua_State *L); static int lua_set_variable(lua_State *L); static int lua_func_read(lua_State *L); static int lua_autoservice_start(lua_State *L); static int lua_autoservice_stop(lua_State *L); static int lua_autoservice_status(lua_State *L); static int lua_check_hangup(lua_State *L); static int lua_error_function(lua_State *L); static void lua_update_registry(lua_State *L, const char *context, const char *exten, int priority); static void lua_push_variable_table(lua_State *L, const char *name); static void lua_create_app_table(lua_State *L); static void lua_create_channel_table(lua_State *L); static void lua_create_variable_metatable(lua_State *L); static void lua_create_application_metatable(lua_State *L); static void lua_create_autoservice_functions(lua_State *L); static void lua_create_hangup_function(lua_State *L); void lua_state_destroy(void *data); static lua_State *lua_get_state(struct ast_channel *chan); static int exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data); static int canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data); static int matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data); static int exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data); AST_MUTEX_DEFINE_STATIC(config_file_lock); char *config_file_data = NULL; long config_file_size = 0; static struct ast_context *local_contexts = NULL; static struct ast_hashtab *local_table = NULL; static const struct ast_datastore_info lua_datastore = { .type = "lua", .destroy = lua_state_destroy, }; /*! * \brief The destructor for lua_datastore */ void lua_state_destroy(void *data) { if (data) lua_close(data); } /*! * \brief [lua_CFunction] Find an app and return it in a lua table (for access from lua, don't * call directly) * * This function would be called in the following example as it would be found * in extensions.lua. * * \code * app.dial * \endcode */ static int lua_pbx_findapp(lua_State *L) { const char *app_name = luaL_checkstring(L, 2); lua_newtable(L); lua_pushstring(L, "name"); lua_pushstring(L, app_name); lua_settable(L, -3); luaL_getmetatable(L, "application"); lua_setmetatable(L, -2); return 1; } /*! * \brief [lua_CFunction] This function is part of the 'application' metatable * and is used to execute applications similar to pbx_exec() (for access from * lua, don't call directly) * * \param L the lua_State to use * \return nothing * * This funciton is executed as the '()' operator for apps accessed through the * 'app' table. * * \code * app.playback('demo-congrats') * \endcode */ static int lua_pbx_exec(lua_State *L) { int res, nargs = lua_gettop(L); char data[LUA_EXT_DATA_SIZE] = ""; char *data_next = data, *app_name; char *context, *exten; char tmp[80], tmp2[80], tmp3[LUA_EXT_DATA_SIZE]; int priority, autoservice; size_t data_left = sizeof(data); struct ast_app *app; struct ast_channel *chan; lua_getfield(L, 1, "name"); app_name = ast_strdupa(lua_tostring(L, -1)); lua_pop(L, 1); if (!(app = pbx_findapp(app_name))) { lua_pushstring(L, "application '"); lua_pushstring(L, app_name); lua_pushstring(L, "' not found"); lua_concat(L, 3); return lua_error(L); } lua_getfield(L, LUA_REGISTRYINDEX, "channel"); chan = lua_touserdata(L, -1); lua_pop(L, 1); lua_getfield(L, LUA_REGISTRYINDEX, "context"); context = ast_strdupa(lua_tostring(L, -1)); lua_pop(L, 1); lua_getfield(L, LUA_REGISTRYINDEX, "exten"); exten = ast_strdupa(lua_tostring(L, -1)); lua_pop(L, 1); lua_getfield(L, LUA_REGISTRYINDEX, "priority"); priority = lua_tointeger(L, -1); lua_pop(L, 1); if (nargs > 1) { int i; if (!lua_isnil(L, 2)) ast_build_string(&data_next, &data_left, "%s", luaL_checkstring(L, 2)); for (i = 3; i <= nargs; i++) { if (lua_isnil(L, i)) ast_build_string(&data_next, &data_left, ","); else ast_build_string(&data_next, &data_left, ",%s", luaL_checkstring(L, i)); } } ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\")\n", exten, context, priority, term_color(tmp, app_name, COLOR_BRCYAN, 0, sizeof(tmp)), term_color(tmp2, chan->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), term_color(tmp3, data, COLOR_BRMAGENTA, 0, sizeof(tmp3))); lua_getfield(L, LUA_REGISTRYINDEX, "autoservice"); autoservice = lua_toboolean(L, -1); lua_pop(L, 1); if (autoservice) ast_autoservice_stop(chan); res = pbx_exec(chan, app, data); if (autoservice) ast_autoservice_start(chan); /* error executing an application, report it */ if (res) { lua_pushinteger(L, res); return lua_error(L); } return 0; } /*! * \brief [lua_CFunction] Used to get the value of a variable or dialplan * function (for access from lua, don't call directly) * * The value of the variable or function is returned. This function is the * 'get()' function in the following example as would be seen in * extensions.lua. * * \code * channel.variable:get() * \endcode */ static int lua_get_variable_value(lua_State *L) { struct ast_channel *chan; char *value = NULL, *name; char *workspace = alloca(LUA_BUF_SIZE); int autoservice; workspace[0] = '\0'; if (!lua_istable(L, 1)) { lua_pushstring(L, "User probably used '.' instead of ':' for retrieving a channel variable value"); return lua_error(L); } lua_getfield(L, LUA_REGISTRYINDEX, "channel"); chan = lua_touserdata(L, -1); lua_pop(L, 1); lua_getfield(L, 1, "name"); name = ast_strdupa(lua_tostring(L, -1)); lua_pop(L, 1); lua_getfield(L, LUA_REGISTRYINDEX, "autoservice"); autoservice = lua_toboolean(L, -1); lua_pop(L, 1); if (autoservice) ast_autoservice_stop(chan); /* if this is a dialplan function then use ast_func_read(), otherwise * use pbx_retrieve_variable() */ if (!ast_strlen_zero(name) && name[strlen(name) - 1] == ')') { value = ast_func_read(chan, name, workspace, LUA_BUF_SIZE) ? NULL : workspace; } else { pbx_retrieve_variable(chan, name, &value, workspace, LUA_BUF_SIZE, &chan->varshead); } if (autoservice) ast_autoservice_start(chan); if (value) { lua_pushstring(L, value); } else { lua_pushnil(L); } return 1; } /*! * \brief [lua_CFunction] Used to set the value of a variable or dialplan * function (for access from lua, don't call directly) * * This function is the 'set()' function in the following example as would be * seen in extensions.lua. * * \code * channel.variable:set("value") * \endcode */ static int lua_set_variable_value(lua_State *L) { const char *name, *value; struct ast_channel *chan; int autoservice; if (!lua_istable(L, 1)) { lua_pushstring(L, "User probably used '.' instead of ':' for setting a channel variable"); return lua_error(L); } lua_getfield(L, 1, "name"); name = ast_strdupa(lua_tostring(L, -1)); lua_pop(L, 1); value = luaL_checkstring(L, 2); lua_getfield(L, LUA_REGISTRYINDEX, "channel"); chan = lua_touserdata(L, -1); lua_pop(L, 1); lua_getfield(L, LUA_REGISTRYINDEX, "autoservice"); autoservice = lua_toboolean(L, -1); lua_pop(L, 1); if (autoservice) ast_autoservice_stop(chan); pbx_builtin_setvar_helper(chan, name, value); if (autoservice) ast_autoservice_start(chan); return 0; } /*! * \brief Update the lua registry with the given context, exten, and priority. * * \param L the lua_State to use * \param context the new context * \param exten the new exten * \param priority the new priority */ static void lua_update_registry(lua_State *L, const char *context, const char *exten, int priority) { lua_pushstring(L, context); lua_setfield(L, LUA_REGISTRYINDEX, "context"); lua_pushstring(L, exten); lua_setfield(L, LUA_REGISTRYINDEX, "exten"); lua_pushinteger(L, priority); lua_setfield(L, LUA_REGISTRYINDEX, "priority"); } /*! * \brief Push a 'variable' table on the stack for access the channel variable * with the given name. * * \param L the lua_State to use * \param name the name of the variable */ static void lua_push_variable_table(lua_State *L, const char *name) { lua_newtable(L); luaL_getmetatable(L, "variable"); lua_setmetatable(L, -2); lua_pushstring(L, name); lua_setfield(L, -2, "name"); lua_pushcfunction(L, &lua_get_variable_value); lua_setfield(L, -2, "get"); lua_pushcfunction(L, &lua_set_variable_value); lua_setfield(L, -2, "set"); } /*! * \brief Create the global 'app' table for executing applications * * \param L the lua_State to use */ static void lua_create_app_table(lua_State *L) { lua_newtable(L); luaL_newmetatable(L, "app"); lua_pushstring(L, "__index"); lua_pushcfunction(L, &lua_pbx_findapp); lua_settable(L, -3); lua_setmetatable(L, -2); lua_setglobal(L, "app"); } /*! * \brief Create the global 'channel' table for accesing channel variables * * \param L the lua_State to use */ static void lua_create_channel_table(lua_State *L) { lua_newtable(L); luaL_newmetatable(L, "channel_data"); lua_pushstring(L, "__index"); lua_pushcfunction(L, &lua_get_variable); lua_settable(L, -3); lua_pushstring(L, "__newindex"); lua_pushcfunction(L, &lua_set_variable); lua_settable(L, -3); lua_setmetatable(L, -2); lua_setglobal(L, "channel"); } /*! * \brief Create the 'variable' metatable, used to retrieve channel variables * * \param L the lua_State to use */ static void lua_create_variable_metatable(lua_State *L) { luaL_newmetatable(L, "variable"); lua_pushstring(L, "__call"); lua_pushcfunction(L, &lua_func_read); lua_settable(L, -3); lua_pop(L, 1); } /*! * \brief Create the 'application' metatable, used to execute asterisk * applications from lua * * \param L the lua_State to use */ static void lua_create_application_metatable(lua_State *L) { luaL_newmetatable(L, "application"); lua_pushstring(L, "__call"); lua_pushcfunction(L, &lua_pbx_exec); lua_settable(L, -3); lua_pop(L, 1); } /*! * \brief Create the autoservice functions * * \param L the lua_State to use */ static void lua_create_autoservice_functions(lua_State *L) { lua_pushcfunction(L, &lua_autoservice_start); lua_setglobal(L, "autoservice_start"); lua_pushcfunction(L, &lua_autoservice_stop); lua_setglobal(L, "autoservice_stop"); lua_pushcfunction(L, &lua_autoservice_status); lua_setglobal(L, "autoservice_status"); lua_pushboolean(L, 0); lua_setfield(L, LUA_REGISTRYINDEX, "autoservice"); } /*! * \brief Create the hangup check function * * \param L the lua_State to use */ static void lua_create_hangup_function(lua_State *L) { lua_pushcfunction(L, &lua_check_hangup); lua_setglobal(L, "check_hangup"); } /*! * \brief [lua_CFunction] Return a lua 'variable' object (for access from lua, don't call * directly) * * This function is called to lookup a variable construct a 'variable' object. * It would be called in the following example as would be seen in * extensions.lua. * * \code * channel.variable * \endcode */ static int lua_get_variable(lua_State *L) { struct ast_channel *chan; char *name = ast_strdupa(luaL_checkstring(L, 2)); char *value = NULL; char *workspace = alloca(LUA_BUF_SIZE); workspace[0] = '\0'; lua_getfield(L, LUA_REGISTRYINDEX, "channel"); chan = lua_touserdata(L, -1); lua_pop(L, 1); lua_push_variable_table(L, name); /* if this is not a request for a dialplan funciton attempt to retrieve * the value of the variable */ if (!ast_strlen_zero(name) && name[strlen(name) - 1] != ')') { pbx_retrieve_variable(chan, name, &value, workspace, LUA_BUF_SIZE, &chan->varshead); } if (value) { lua_pushstring(L, value); lua_setfield(L, -2, "value"); } return 1; } /*! * \brief [lua_CFunction] Set the value of a channel variable or dialplan * function (for access from lua, don't call directly) * * This function is called to set a variable or dialplan function. It would be * called in the following example as would be seen in extensions.lua. * * \code * channel.variable = "value" * \endcode */ static int lua_set_variable(lua_State *L) { struct ast_channel *chan; int autoservice; const char *name = luaL_checkstring(L, 2); const char *value = luaL_checkstring(L, 3); lua_getfield(L, LUA_REGISTRYINDEX, "channel"); chan = lua_touserdata(L, -1); lua_pop(L, 1); lua_getfield(L, LUA_REGISTRYINDEX, "autoservice"); autoservice = lua_toboolean(L, -1); lua_pop(L, 1); if (autoservice) ast_autoservice_stop(chan); pbx_builtin_setvar_helper(chan, name, value); if (autoservice) ast_autoservice_start(chan); return 0; } /*! * \brief [lua_CFunction] Create a 'variable' object for accessing a dialplan * function (for access from lua, don't call directly) * * This function is called to create a 'variable' object to access a dialplan * function. It would be called in the following example as would be seen in * extensions.lua. * * \code * channel.func("arg1", "arg2", "arg3") * \endcode * * To actually do anything with the resulting value you must use the 'get()' * and 'set()' methods (the reason is the resulting value is not a value, but * an object in the form of a lua table). */ static int lua_func_read(lua_State *L) { int nargs = lua_gettop(L); char fullname[LUA_EXT_DATA_SIZE] = ""; char *fullname_next = fullname, *name; size_t fullname_left = sizeof(fullname); lua_getfield(L, 1, "name"); name = ast_strdupa(lua_tostring(L, -1)); lua_pop(L, 1); ast_build_string(&fullname_next, &fullname_left, "%s(", name); if (nargs > 1) { int i; if (!lua_isnil(L, 2)) ast_build_string(&fullname_next, &fullname_left, "%s", luaL_checkstring(L, 2)); for (i = 3; i <= nargs; i++) { if (lua_isnil(L, i)) ast_build_string(&fullname_next, &fullname_left, ","); else ast_build_string(&fullname_next, &fullname_left, ",%s", luaL_checkstring(L, i)); } } ast_build_string(&fullname_next, &fullname_left, ")"); lua_push_variable_table(L, fullname); return 1; } /*! * \brief [lua_CFunction] Tell pbx_lua to maintain an autoservice on this * channel (for access from lua, don't call directly) * * \param L the lua_State to use * * This function will set a flag that will cause pbx_lua to maintain an * autoservice on this channel. The autoservice will automatically be stopped * and restarted before calling applications and functions. * * \return This function returns the result of the ast_autoservice_start() * function as a boolean to its lua caller. */ static int lua_autoservice_start(lua_State *L) { struct ast_channel *chan; int res; lua_getfield(L, LUA_REGISTRYINDEX, "channel"); chan = lua_touserdata(L, -1); lua_pop(L, 1); res = ast_autoservice_start(chan); lua_pushboolean(L, !res); lua_setfield(L, LUA_REGISTRYINDEX, "autoservice"); lua_pushboolean(L, !res); return 1; } /*! * \brief [lua_CFunction] Tell pbx_lua to stop maintaning an autoservice on * this channel (for access from lua, don't call directly) * * \param L the lua_State to use * * This function will stop any autoservice running and turn off the autoservice * flag. If this function returns false, it's probably because no autoservice * was running to begin with. * * \return This function returns the result of the ast_autoservice_stop() * function as a boolean to its lua caller. */ static int lua_autoservice_stop(lua_State *L) { struct ast_channel *chan; int res; lua_getfield(L, LUA_REGISTRYINDEX, "channel"); chan = lua_touserdata(L, -1); lua_pop(L, 1); res = ast_autoservice_stop(chan); lua_pushboolean(L, 0); lua_setfield(L, LUA_REGISTRYINDEX, "autoservice"); lua_pushboolean(L, !res); return 1; } /*! * \brief [lua_CFunction] Get the status of the autoservice flag (for access * from lua, don't call directly) * * \param L the lua_State to use * * \return This function returns the status of the autoservice flag as a * boolean to its lua caller. */ static int lua_autoservice_status(lua_State *L) { lua_getfield(L, LUA_REGISTRYINDEX, "autoservice"); return 1; } /*! * \brief [lua_CFunction] Check if this channel has been hungup or not (for * access from lua, don't call directly) * * \param L the lua_State to use * * \return This function returns true if the channel was hungup */ static int lua_check_hangup(lua_State *L) { struct ast_channel *chan; lua_getfield(L, LUA_REGISTRYINDEX, "channel"); chan = lua_touserdata(L, -1); lua_pop(L, 1); lua_pushboolean(L, ast_check_hangup(chan)); return 1; } /*! * \brief [lua_CFunction] Handle lua errors (for access from lua, don't call * directly) * * \param L the lua_State to use */ static int lua_error_function(lua_State *L) { int message_index; /* pass number arguments right through back to asterisk*/ if (lua_isnumber(L, -1)) { return 1; } /* if we are here then we have a string error message, let's attach a * backtrace to it */ message_index = lua_gettop(L); lua_getglobal(L, "debug"); lua_getfield(L, -1, "traceback"); lua_remove(L, -2); /* remove the 'debug' table */ lua_pushvalue(L, message_index); lua_remove(L, message_index); lua_pushnumber(L, 2); lua_call(L, 2, 1); return 1; } /*! * \brief Store the sort order of each context * In the event of an error, an error string will be pushed onto the lua stack. * * \retval 0 success * \retval 1 failure */ static int lua_sort_extensions(lua_State *L) { int extensions, extensions_order; /* create the extensions_order table */ lua_newtable(L); lua_setfield(L, LUA_REGISTRYINDEX, "extensions_order"); lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order"); extensions_order = lua_gettop(L); /* sort each context in the extensions table */ /* load the 'extensions' table */ lua_getglobal(L, "extensions"); extensions = lua_gettop(L); if (lua_isnil(L, -1)) { lua_pop(L, 1); lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n"); return 1; } /* iterate through the extensions table and create a * matching table (holding the sort order) in the * extensions_order table for each context that is found */ for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) { int context = lua_gettop(L); int context_name = context - 1; int context_order; lua_pushvalue(L, context_name); lua_newtable(L); context_order = lua_gettop(L); /* iterate through this context an popluate the corrisponding * table in the extensions_order table */ for (lua_pushnil(L); lua_next(L, context); lua_pop(L, 1)) { int exten = lua_gettop(L) - 1; lua_pushinteger(L, lua_objlen(L, context_order) + 1); lua_pushvalue(L, exten); lua_settable(L, context_order); } lua_settable(L, extensions_order); /* put the context_order table in the extensions_order table */ /* now sort the new table */ /* push the table.sort function */ lua_getglobal(L, "table"); lua_getfield(L, -1, "sort"); lua_remove(L, -2); /* remove the 'table' table */ /* push the context_order table */ lua_pushvalue(L, context_name); lua_gettable(L, extensions_order); /* push the comp function */ lua_pushcfunction(L, &lua_extension_cmp); if (lua_pcall(L, 2, 0, 0)) { lua_insert(L, -5); lua_pop(L, 4); return 1; } } /* remove the extensions table and the extensions_order table */ lua_pop(L, 2); return 0; } /*! * \brief Register dialplan switches for our pbx_lua contexs. * * In the event of an error, an error string will be pushed onto the lua stack. * * \retval 0 success * \retval 1 failure */ static int lua_register_switches(lua_State *L) { int extensions; struct ast_context *con = NULL; /* create the hash table for our contexts */ /* XXX do we ever need to destroy this? pbx_config does not */ if (!local_table) local_table = ast_hashtab_create(17, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0); /* load the 'extensions' table */ lua_getglobal(L, "extensions"); extensions = lua_gettop(L); if (lua_isnil(L, -1)) { lua_pop(L, 1); lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n"); return 1; } /* iterate through the extensions table and register a context and * dialplan switch for each lua context */ for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) { int context = lua_gettop(L); int context_name = context - 1; const char *context_str = lua_tostring(L, context_name); /* find or create this context */ con = ast_context_find_or_create(&local_contexts, local_table, context_str, registrar); if (!con) { /* remove extensions table and context key and value */ lua_pop(L, 3); lua_pushstring(L, "Failed to find or create context\n"); return 1; } /* register the switch */ if (ast_context_add_switch2(con, "Lua", "", 0, registrar)) { /* remove extensions table and context key and value */ lua_pop(L, 3); lua_pushstring(L, "Unable to create switch for context\n"); return 1; } } /* remove the extensions table */ lua_pop(L, 1); return 0; } /*! * \brief [lua_CFunction] Compare two extensions (for access from lua, don't * call directly) * * This function returns true if the first extension passed should match after * the second. It behaves like the '<' operator. */ static int lua_extension_cmp(lua_State *L) { const char *a = luaL_checkstring(L, -2); const char *b = luaL_checkstring(L, -1); if (ast_extension_cmp(a, b) == -1) lua_pushboolean(L, 1); else lua_pushboolean(L, 0); return 1; } /*! * \brief Load the extensions.lua file in to a buffer and execute the file * * \param L the lua_State to use * \param size a pointer to store the size of the buffer * * \note The caller is expected to free the buffer at some point. * * \return a pointer to the buffer */ static char *lua_read_extensions_file(lua_State *L, long *size) { FILE *f; char *data; char *path = alloca(strlen(config) + strlen(ast_config_AST_CONFIG_DIR) + 2); sprintf(path, "%s/%s", ast_config_AST_CONFIG_DIR, config); if (!(f = fopen(path, "r"))) { lua_pushstring(L, "cannot open '"); lua_pushstring(L, path); lua_pushstring(L, "' for reading: "); lua_pushstring(L, strerror(errno)); lua_concat(L, 4); return NULL; } fseek(f, 0l, SEEK_END); *size = ftell(f); fseek(f, 0l, SEEK_SET); if (!(data = ast_malloc(*size))) { *size = 0; fclose(f); lua_pushstring(L, "not enough memory"); return NULL; } if (fread(data, sizeof(char), *size, f) != *size) { ast_log(LOG_WARNING, "fread() failed: %s\n", strerror(errno)); } fclose(f); if (luaL_loadbuffer(L, data, *size, "extensions.lua") || lua_pcall(L, 0, LUA_MULTRET, 0) || lua_sort_extensions(L) || lua_register_switches(L)) { ast_free(data); data = NULL; *size = 0; } return data; } /*! * \brief Load the extensions.lua file from the internal buffer * * \param L the lua_State to use * \param chan channel to work on * * This function also sets up some constructs used by the extensions.lua file. * In the event of an error, an error string will be pushed onto the lua stack. * * \retval 0 success * \retval 1 failure */ static int lua_load_extensions(lua_State *L, struct ast_channel *chan) { /* store a pointer to this channel */ lua_pushlightuserdata(L, chan); lua_setfield(L, LUA_REGISTRYINDEX, "channel"); luaL_openlibs(L); /* load and sort extensions */ ast_mutex_lock(&config_file_lock); if (luaL_loadbuffer(L, config_file_data, config_file_size, "extensions.lua") || lua_pcall(L, 0, LUA_MULTRET, 0) || lua_sort_extensions(L)) { ast_mutex_unlock(&config_file_lock); return 1; } ast_mutex_unlock(&config_file_lock); /* now we setup special tables and functions */ lua_create_app_table(L); lua_create_channel_table(L); lua_create_variable_metatable(L); lua_create_application_metatable(L); lua_create_autoservice_functions(L); lua_create_hangup_function(L); return 0; } /*! * \brief Reload the extensions file and update the internal buffers if it * loads correctly. * * \warning This function should not be called on a lua_State returned from * lua_get_state(). * * \param L the lua_State to use (must be freshly allocated with * luaL_newstate(), don't use lua_get_state()) */ static int lua_reload_extensions(lua_State *L) { long size = 0; char *data = NULL; luaL_openlibs(L); if (!(data = lua_read_extensions_file(L, &size))) { return 1; } ast_mutex_lock(&config_file_lock); if (config_file_data) ast_free(config_file_data); config_file_data = data; config_file_size = size; /* merge our new contexts */ ast_merge_contexts_and_delete(&local_contexts, local_table, registrar); /* merge_contexts_and_delete will actually, at the correct moment, set the global dialplan pointers to your local_contexts and local_table. It then will free up the old tables itself. Just be sure not to hang onto the pointers. */ local_table = NULL; local_contexts = NULL; ast_mutex_unlock(&config_file_lock); return 0; } /*! * \brief Free the internal extensions buffer. */ static void lua_free_extensions() { ast_mutex_lock(&config_file_lock); config_file_size = 0; ast_free(config_file_data); ast_mutex_unlock(&config_file_lock); } /*! * \brief Get the lua_State for this channel * * If no channel is passed then a new state is allocated. States with no * channel assocatied with them should only be used for matching extensions. * If the channel does not yet have a lua state associated with it, one will be * created. * * \note If no channel was passed then the caller is expected to free the state * using lua_close(). * * \return a lua_State */ static lua_State *lua_get_state(struct ast_channel *chan) { struct ast_datastore *datastore = NULL; lua_State *L; if (!chan) { lua_State *L = luaL_newstate(); if (!L) { ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n"); return NULL; } if (lua_load_extensions(L, NULL)) { const char *error = lua_tostring(L, -1); ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error); lua_close(L); return NULL; } return L; } else { ast_channel_lock(chan); datastore = ast_channel_datastore_find(chan, &lua_datastore, NULL); ast_channel_unlock(chan); if (!datastore) { /* nothing found, allocate a new lua state */ datastore = ast_datastore_alloc(&lua_datastore, NULL); if (!datastore) { ast_log(LOG_ERROR, "Error allocation channel datastore for lua_State\n"); return NULL; } datastore->data = luaL_newstate(); if (!datastore->data) { ast_datastore_free(datastore); ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n"); return NULL; } ast_channel_lock(chan); ast_channel_datastore_add(chan, datastore); ast_channel_unlock(chan); L = datastore->data; if (lua_load_extensions(L, chan)) { const char *error = lua_tostring(L, -1); ast_log(LOG_ERROR, "Error loading extensions.lua for %s: %s\n", chan->name, error); ast_channel_lock(chan); ast_channel_datastore_remove(chan, datastore); ast_channel_unlock(chan); ast_datastore_free(datastore); return NULL; } } return datastore->data; } } static int exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) { int res; lua_State *L; struct ast_module_user *u = ast_module_user_add(chan); if (!u) { ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n"); return 0; } L = lua_get_state(chan); if (!L) { ast_module_user_remove(u); return 0; } res = lua_find_extension(L, context, exten, priority, &exists, 0); if (!chan) lua_close(L); ast_module_user_remove(u); return res; } static int canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) { int res; lua_State *L; struct ast_module_user *u = ast_module_user_add(chan); if (!u) { ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n"); return 0; } L = lua_get_state(chan); if (!L) { ast_module_user_remove(u); return 0; } res = lua_find_extension(L, context, exten, priority, &canmatch, 0); if (!chan) lua_close(L); ast_module_user_remove(u); return res; } static int matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) { int res; lua_State *L; struct ast_module_user *u = ast_module_user_add(chan); if (!u) { ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n"); return 0; } L = lua_get_state(chan); if (!L) { ast_module_user_remove(u); return 0; } res = lua_find_extension(L, context, exten, priority, &matchmore, 0); if (!chan) lua_close(L); ast_module_user_remove(u); return res; } static int exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) { int res, error_func; lua_State *L; struct ast_module_user *u = ast_module_user_add(chan); if (!u) { ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n"); return -1; } L = lua_get_state(chan); if (!L) { ast_module_user_remove(u); return -1; } lua_pushcfunction(L, &lua_error_function); error_func = lua_gettop(L); /* push the extension function onto the stack */ if (!lua_find_extension(L, context, exten, priority, &exists, 1)) { lua_pop(L, 1); /* pop the debug function */ ast_log(LOG_ERROR, "Could not find extension %s in context %s\n", exten, context); if (!chan) lua_close(L); ast_module_user_remove(u); return -1; } lua_update_registry(L, context, exten, priority); lua_pushstring(L, context); lua_pushstring(L, exten); res = lua_pcall(L, 2, 0, error_func); if (res) { if (res == LUA_ERRRUN) { res = -1; if (lua_isnumber(L, -1)) { res = lua_tointeger(L, -1); } else if (lua_isstring(L, -1)) { const char *error = lua_tostring(L, -1); ast_log(LOG_ERROR, "Error executing lua extension: %s\n", error); } } else if (res == LUA_ERRERR) { res = -1; ast_log(LOG_ERROR, "Error in the lua error handler (this is probably a bug in pbx_lua)\n"); } else if (res == LUA_ERRMEM) { res = -1; ast_log(LOG_ERROR, "Memory allocation error\n"); } lua_pop(L, 1); } lua_remove(L, error_func); if (!chan) lua_close(L); ast_module_user_remove(u); return res; } /*! * \brief Locate an extensions and optionally push the matching function on the * stack * * \param L the lua_State to use * \param context the context to look in * \param exten the extension to look up * \param priority the priority to check, '1' is the only valid priority * \param func the calling func, used to adjust matching behavior between, * match, canmatch, and matchmore * \param push_func whether or not to push the lua function for the given * extension onto the stack */ static int lua_find_extension(lua_State *L, const char *context, const char *exten, int priority, ast_switch_f *func, int push_func) { int context_table, context_order_table, i; ast_debug(2, "Looking up %s@%s:%i\n", exten, context, priority); if (priority != 1) return 0; /* load the 'extensions' table */ lua_getglobal(L, "extensions"); if (lua_isnil(L, -1)) { ast_log(LOG_ERROR, "Unable to find 'extensions' table in extensions.lua\n"); lua_pop(L, 1); return 0; } /* load the given context */ lua_getfield(L, -1, context); if (lua_isnil(L, -1)) { lua_pop(L, 2); return 0; } /* remove the extensions table */ lua_remove(L, -2); context_table = lua_gettop(L); /* load the extensions order table for this context */ lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order"); lua_getfield(L, -1, context); lua_remove(L, -2); /* remove the extensions order table */ context_order_table = lua_gettop(L); /* step through the extensions looking for a match */ for (i = 1; i < lua_objlen(L, context_order_table) + 1; i++) { int e_index, e_index_copy, match = 0; const char *e; lua_pushinteger(L, i); lua_gettable(L, context_order_table); e_index = lua_gettop(L); /* copy the key at the top of the stack for use later */ lua_pushvalue(L, -1); e_index_copy = lua_gettop(L); if (!(e = lua_tostring(L, e_index_copy))) { lua_pop(L, 2); continue; } /* make sure this is not the 'include' extension */ if (!strcasecmp(e, "include")) { lua_pop(L, 2); continue; } if (func == &matchmore) match = ast_extension_close(e, exten, E_MATCHMORE); else if (func == &canmatch) match = ast_extension_close(e, exten, E_CANMATCH); else match = ast_extension_match(e, exten); /* the extension matching functions return 0 on fail, 1 on * match, 2 on earlymatch */ if (!match) { /* pop the copy and the extension */ lua_pop(L, 2); continue; /* keep trying */ } if (func == &matchmore && match == 2) { /* We match an extension ending in '!'. The decision in * this case is final and counts as no match. */ lua_pop(L, 4); return 0; } /* remove the context table, the context order table, the * extension, and the extension copy (or replace the extension * with the corresponding function) */ if (push_func) { lua_pop(L, 1); /* pop the copy */ lua_gettable(L, context_table); lua_insert(L, -3); lua_pop(L, 2); } else { lua_pop(L, 4); } return 1; } /* load the includes for this context */ lua_getfield(L, context_table, "include"); if (lua_isnil(L, -1)) { lua_pop(L, 3); return 0; } /* remove the context and the order table*/ lua_remove(L, context_order_table); lua_remove(L, context_table); /* Now try any includes we have in this context */ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { const char *c = lua_tostring(L, -1); if (!c) continue; if (lua_find_extension(L, c, exten, priority, func, push_func)) { /* remove the value, the key, and the includes table * from the stack. Leave the function behind if * necessary */ if (push_func) lua_insert(L, -4); lua_pop(L, 3); return 1; } } /* pop the includes table */ lua_pop(L, 1); return 0; } static struct ast_switch lua_switch = { .name = "Lua", .description = "Lua PBX Switch", .exists = exists, .canmatch = canmatch, .exec = exec, .matchmore = matchmore, }; static int load_or_reload_lua_stuff(void) { int res = AST_MODULE_LOAD_SUCCESS; lua_State *L = luaL_newstate(); if (!L) { ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n"); return AST_MODULE_LOAD_DECLINE; } if (lua_reload_extensions(L)) { const char *error = lua_tostring(L, -1); ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error); res = AST_MODULE_LOAD_DECLINE; } lua_close(L); return res; } static int unload_module(void) { ast_context_destroy(NULL, registrar); ast_unregister_switch(&lua_switch); lua_free_extensions(); return 0; } static int reload(void) { return load_or_reload_lua_stuff(); } static int load_module(void) { int res; if ((res = load_or_reload_lua_stuff())) return res; if (ast_register_switch(&lua_switch)) { ast_log(LOG_ERROR, "Unable to register LUA PBX switch\n"); return AST_MODULE_LOAD_DECLINE; } return AST_MODULE_LOAD_SUCCESS; } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Lua PBX Switch", .load = load_module, .unload = unload_module, .reload = reload, ); asterisk-1.6.1.0/pbx/pbx_config.c0000644000175000017500000014264211155637431016036 0ustar maniacmaniac/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 1999 - 2006, Digium, Inc. * * Mark Spencer * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. */ /*! \file * * \brief Populate and remember extensions from static config file * * */ #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision: 181199 $") #include #include "asterisk/paths.h" /* ast_config_AST_CONFIG_DIR */ #include "asterisk/pbx.h" #include "asterisk/config.h" #include "asterisk/module.h" #include "asterisk/logger.h" #include "asterisk/cli.h" #include "asterisk/channel.h" /* AST_MAX_EXTENSION */ #include "asterisk/callerid.h" static char *config = "extensions.conf"; static char *registrar = "pbx_config"; static char userscontext[AST_MAX_EXTENSION] = "default"; static int static_config = 0; static int write_protect_config = 1; static int autofallthrough_config = 1; static int clearglobalvars_config = 0; static int extenpatternmatchnew_config = 0; static char *overrideswitch_config = NULL; AST_MUTEX_DEFINE_STATIC(save_dialplan_lock); static struct ast_context *local_contexts = NULL; static struct ast_hashtab *local_table = NULL; /* * Prototypes for our completion functions */ static char *complete_dialplan_remove_include(struct ast_cli_args *); static char *complete_dialplan_add_include(struct ast_cli_args *); static char *complete_dialplan_remove_ignorepat(struct ast_cli_args *); static char *complete_dialplan_add_ignorepat(struct ast_cli_args *); static char *complete_dialplan_remove_extension(struct ast_cli_args *); static char *complete_dialplan_add_extension(struct ast_cli_args *); /* * Implementation of functions provided by this module */ /*! * REMOVE INCLUDE command stuff */ static char *handle_cli_dialplan_remove_include(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { switch (cmd) { case CLI_INIT: e->command = "dialplan remove include"; e->usage = "Usage: dialplan remove include from \n" " Remove an included context from another context.\n"; return NULL; case CLI_GENERATE: return complete_dialplan_remove_include(a); } if (strcmp(a->argv[4], "from")) return CLI_SHOWUSAGE; if (!ast_context_remove_include(a->argv[5], a->argv[3], registrar)) { ast_cli(a->fd, "We are not including '%s' into '%s' now\n", a->argv[3], a->argv[5]); return CLI_SUCCESS; } ast_cli(a->fd, "Failed to remove '%s' include from '%s' context\n", a->argv[3], a->argv[5]); return CLI_FAILURE; } /*! \brief return true if 'name' is included by context c */ static int lookup_ci(struct ast_context *c, const char *name) { struct ast_include *i = NULL; if (ast_rdlock_context(c)) /* error, skip */ return 0; while ( (i = ast_walk_context_includes(c, i)) ) if (!strcmp(name, ast_get_include_name(i))) break; ast_unlock_context(c); return i ? -1 /* success */ : 0; } /*! \brief return true if 'name' is in the ignorepats for context c */ static int lookup_c_ip(struct ast_context *c, const char *name) { struct ast_ignorepat *ip = NULL; if (ast_rdlock_context(c)) /* error, skip */ return 0; while ( (ip = ast_walk_context_ignorepats(c, ip)) ) if (!strcmp(name, ast_get_ignorepat_name(ip))) break; ast_unlock_context(c); return ip ? -1 /* success */ : 0; } /*! \brief moves to the n-th word in the string, or empty string if none */ static const char *skip_words(const char *p, int n) { int in_blank = 0; for (;n && *p; p++) { if (isblank(*p) /* XXX order is important */ && !in_blank) { n--; /* one word is gone */ in_blank = 1; } else if (/* !is_blank(*p), we know already, && */ in_blank) { in_blank = 0; } } return p; } /*! \brief match the first 'len' chars of word. len==0 always succeeds */ static int partial_match(const char *s, const char *word, int len) { return (len == 0 || !strncmp(s, word, len)); } /*! \brief split extension\@context in two parts, return -1 on error. * The return string is malloc'ed and pointed by *ext */ static int split_ec(const char *src, char **ext, char ** const ctx, char ** const cid) { char *i, *c, *e = ast_strdup(src); /* now src is not used anymore */ if (e == NULL) return -1; /* malloc error */ /* now, parse values from 'exten@context' */ *ext = e; c = strchr(e, '@'); if (c == NULL) /* no context part */ *ctx = ""; /* it is not overwritten, anyways */ else { /* found context, check for duplicity ... */ *c++ = '\0'; *ctx = c; if (strchr(c, '@')) { /* two @, not allowed */ free(e); return -1; } } if (cid && (i = strchr(e, '/'))) { *i++ = '\0'; *cid = i; } else if (cid) { /* Signal none detected */ *cid = NULL; } return 0; } /* _X_ is the string we need to complete */ static char *complete_dialplan_remove_include(struct ast_cli_args *a) { int which = 0; char *res = NULL; int len = strlen(a->word); /* how many bytes to match */ struct ast_context *c = NULL; if (a->pos == 3) { /* "dialplan remove include _X_" */ if (ast_wrlock_contexts()) { ast_log(LOG_ERROR, "Failed to lock context list\n"); return NULL; } /* walk contexts and their includes, return the n-th match */ while (!res && (c = ast_walk_contexts(c))) { struct ast_include *i = NULL; if (ast_rdlock_context(c)) /* error ? skip this one */ continue; while ( !res && (i = ast_walk_context_includes(c, i)) ) { const char *i_name = ast_get_include_name(i); struct ast_context *nc = NULL; int already_served = 0; if (!partial_match(i_name, a->word, len)) continue; /* not matched */ /* check if this include is already served or not */ /* go through all contexts again till we reach actual * context or already_served = 1 */ while ( (nc = ast_walk_contexts(nc)) && nc != c && !already_served) already_served = lookup_ci(nc, i_name); if (!already_served && ++which > a->n) res = strdup(i_name); } ast_unlock_context(c); } ast_unlock_contexts(); return res; } else if (a->pos == 4) { /* "dialplan remove include CTX _X_" */ /* * complete as 'from', but only if previous context is really * included somewhere */ char *context, *dupline; const char *s = skip_words(a->line, 3); /* skip 'dialplan' 'remove' 'include' */ if (a->n > 0) return NULL; context = dupline = strdup(s); if (!dupline) { ast_log(LOG_ERROR, "Out of free memory\n"); return NULL; } strsep(&dupline, " "); if (ast_rdlock_contexts()) { ast_log(LOG_ERROR, "Failed to lock contexts list\n"); free(context); return NULL; } /* go through all contexts and check if is included ... */ while (!res && (c = ast_walk_contexts(c))) if (lookup_ci(c, context)) /* context is really included, complete "from" command */ res = strdup("from"); ast_unlock_contexts(); if (!res) ast_log(LOG_WARNING, "%s not included anywhere\n", context); free(context); return res; } else if (a->pos == 5) { /* "dialplan remove include CTX from _X_" */ /* * Context from which we removing include ... */ char *context, *dupline, *from; const char *s = skip_words(a->line, 3); /* skip 'dialplan' 'remove' 'include' */ context = dupline = strdup(s); if (!dupline) { ast_log(LOG_ERROR, "Out of free memory\n"); return NULL; } strsep(&dupline, " "); /* skip context */ /* fourth word must be 'from' */ from = strsep(&dupline, " "); if (!from || strcmp(from, "from")) { free(context); return NULL; } if (ast_rdlock_contexts()) { ast_log(LOG_ERROR, "Failed to lock context list\n"); free(context); return NULL; } /* walk through all contexts ... */ c = NULL; while ( !res && (c = ast_walk_contexts(c))) { const char *c_name = ast_get_context_name(c); if (!partial_match(c_name, a->word, len)) /* not a good target */ continue; /* walk through all includes and check if it is our context */ if (lookup_ci(c, context) && ++which > a->n) res = strdup(c_name); } ast_unlock_contexts(); free(context); return res; } return NULL; } /*! * REMOVE EXTENSION command stuff */ static char *handle_cli_dialplan_remove_extension(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { int removing_priority = 0; char *exten, *context, *cid; char *ret = CLI_FAILURE; switch (cmd) { case CLI_INIT: e->command = "dialplan remove extension"; e->usage = "Usage: dialplan remove extension exten[/cid]@context [priority]\n" " Remove an extension from a given context. If a priority\n" " is given, only that specific priority from the given extension\n" " will be removed.\n"; return NULL; case CLI_GENERATE: return complete_dialplan_remove_extension(a); } if (a->argc != 5 && a->argc != 4) return CLI_SHOWUSAGE; /* * Priority input checking ... */ if (a->argc == 5) { char *c = a->argv[4]; /* check for digits in whole parameter for right priority ... * why? because atoi (strtol) returns 0 if any characters in * string and whole extension will be removed, it's not good */ if (!strcmp("hint", c)) removing_priority = PRIORITY_HINT; else { while (*c && isdigit(*c)) c++; if (*c) { /* non-digit in string */ ast_cli(a->fd, "Invalid priority '%s'\n", a->argv[4]); return CLI_FAILURE; } removing_priority = atoi(a->argv[4]); } if (removing_priority == 0) { ast_cli(a->fd, "If you want to remove whole extension, please " \ "omit priority argument\n"); return CLI_FAILURE; } } /* XXX original overwrote argv[3] */ /* * Format exten@context checking ... */ if (split_ec(a->argv[3], &exten, &context, &cid)) return CLI_FAILURE; /* XXX malloc failure */ if ((!strlen(exten)) || (!(strlen(context)))) { ast_cli(a->fd, "Missing extension or context name in third argument '%s'\n", a->argv[3]); free(exten); return CLI_FAILURE; } if (!ast_context_remove_extension_callerid(context, exten, removing_priority, /* Do NOT substitute S_OR; it is NOT the same thing */ cid ? cid : (removing_priority ? "" : NULL), cid ? 1 : 0, registrar)) { if (!removing_priority) ast_cli(a->fd, "Whole extension %s@%s removed\n", exten, context); else ast_cli(a->fd, "Extension %s@%s with priority %d removed\n", exten, context, removing_priority); ret = CLI_SUCCESS; } else { if (cid) { ast_cli(a->fd, "Failed to remove extension %s/%s@%s\n", exten, cid, context); } else { ast_cli(a->fd, "Failed to remove extension %s@%s\n", exten, context); } ret = CLI_FAILURE; } free(exten); return ret; } #define BROKEN_READLINE 1 #ifdef BROKEN_READLINE /* * There is one funny thing, when you have word like 300@ and you hit * , you arguments will act as your word is '300 ', so the '@' * character acts sometimes as a word delimiter and sometimes as a part * of a word. * * This fix function allocates a new word variable and stores it every * time as xxx@yyy. The correct pos is set, too. * * It's ugly, I know, but I'm waiting for Mark's suggestion if the * previous is a bug or a feature ... */ static int fix_complete_args(const char *line, char **word, int *pos) { char *_line, *_strsep_line, *_previous_word = NULL, *_word = NULL; int words = 0; _line = strdup(line); _strsep_line = _line; while (_strsep_line) { _previous_word = _word; _word = strsep(&_strsep_line, " "); if (_word && strlen(_word)) words++; } if (_word || _previous_word) { if (_word) { if (!strlen(_word)) words++; *word = strdup(_word); } else *word = strdup(_previous_word); *pos = words - 1; free(_line); return 0; } free(_line); return -1; } #endif /* BROKEN_READLINE */ static char *complete_dialplan_remove_extension(struct ast_cli_args *a) { char *ret = NULL; int which = 0; #ifdef BROKEN_READLINE char *word2; /* * Fix arguments, *word is a new allocated structure, REMEMBER to * free *word when you want to return from this function ... */ if (fix_complete_args(a->line, &word2, &a->pos)) { ast_log(LOG_ERROR, "Out of free memory\n"); return NULL; } a->word = word2; #endif if (a->pos == 3) { /* 'dialplan remove extension _X_' (exten@context ... */ struct ast_context *c = NULL; char *context = NULL, *exten = NULL, *cid = NULL; int le = 0; /* length of extension */ int lc = 0; /* length of context */ int lcid = 0; /* length of cid */ lc = split_ec(a->word, &exten, &context, &cid); if (lc) { /* error */ #ifdef BROKEN_READLINE free(word2); #endif return NULL; } le = strlen(exten); lc = strlen(context); lcid = cid ? strlen(cid) : -1; if (ast_rdlock_contexts()) { ast_log(LOG_ERROR, "Failed to lock context list\n"); goto error2; } /* find our context ... */ while ( (c = ast_walk_contexts(c)) ) { /* match our context if any */ struct ast_exten *e = NULL; /* XXX locking ? */ if (!partial_match(ast_get_context_name(c), context, lc)) continue; /* context not matched */ while ( (e = ast_walk_context_extensions(c, e)) ) { /* try to complete extensions ... */ if ( !strchr(a->word, '/') || (!strchr(a->word, '@') && partial_match(ast_get_extension_cidmatch(e), cid, lcid)) || (strchr(a->word, '@') && !strcmp(ast_get_extension_cidmatch(e), cid))) { if ( ((strchr(a->word, '/') || strchr(a->word, '@')) && !strcmp(ast_get_extension_name(e), exten)) || (!strchr(a->word, '/') && !strchr(a->word, '@') && partial_match(ast_get_extension_name(e), exten, le))) { /* n-th match */ if (++which > a->n) { /* If there is an extension then return exten@context. */ if (ast_get_extension_matchcid(e) && (!strchr(a->word, '@') || strchr(a->word, '/'))) { if (asprintf(&ret, "%s/%s@%s", ast_get_extension_name(e), ast_get_extension_cidmatch(e), ast_get_context_name(c)) < 0) { ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); ret = NULL; } break; } else if (!ast_get_extension_matchcid(e) && !strchr(a->word, '/')) { if (asprintf(&ret, "%s@%s", ast_get_extension_name(e), ast_get_context_name(c)) < 0) { ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); ret = NULL; } break; } } } } } if (e) /* got a match */ break; } ast_unlock_contexts(); error2: if (exten) free(exten); } else if (a->pos == 4) { /* 'dialplan remove extension EXT _X_' (priority) */ char *exten = NULL, *context, *cid, *p; struct ast_context *c; int le, lc, lcid, len; const char *s = skip_words(a->line, 3); /* skip 'dialplan' 'remove' 'extension' */ int i = split_ec(s, &exten, &context, &cid); /* parse ext@context */ if (i) /* error */ goto error3; if ( (p = strchr(exten, ' ')) ) /* remove space after extension */ *p = '\0'; if ( (p = strchr(context, ' ')) ) /* remove space after context */ *p = '\0'; le = strlen(exten); lc = strlen(context); lcid = strlen(cid); len = strlen(a->word); if (le == 0 || lc == 0) goto error3; if (ast_rdlock_contexts()) { ast_log(LOG_ERROR, "Failed to lock context list\n"); goto error3; } /* walk contexts */ c = NULL; while ( (c = ast_walk_contexts(c)) ) { /* XXX locking on c ? */ struct ast_exten *e; if (strcmp(ast_get_context_name(c), context) != 0) continue; /* got it, we must match here */ e = NULL; while ( (e = ast_walk_context_extensions(c, e)) ) { struct ast_exten *priority; char buffer[10]; if (cid && strcmp(ast_get_extension_cidmatch(e), cid) != 0) { continue; } if (strcmp(ast_get_extension_name(e), exten) != 0) continue; /* XXX lock e ? */ priority = NULL; while ( !ret && (priority = ast_walk_extension_priorities(e, priority)) ) { snprintf(buffer, sizeof(buffer), "%u", ast_get_extension_priority(priority)); if (partial_match(buffer, a->word, len) && ++which > a->n) /* n-th match */ ret = strdup(buffer); } break; } break; } ast_unlock_contexts(); error3: if (exten) free(exten); } #ifdef BROKEN_READLINE free(word2); #endif return ret; } /*! * Include context ... */ static char *handle_cli_dialplan_add_include(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { switch (cmd) { case CLI_INIT: e->command = "dialplan add include"; e->usage = "Usage: dialplan add include into \n" " Include a context in another context.\n"; return NULL; case CLI_GENERATE: return complete_dialplan_add_include(a); } if (a->argc != 6) /* dialplan add include CTX in CTX */ return CLI_SHOWUSAGE; /* fifth arg must be 'into' ... */ if (strcmp(a->argv[4], "into")) return CLI_SHOWUSAGE; if (ast_context_add_include(a->argv[5], a->argv[3], registrar)) { switch (errno) { case ENOMEM: ast_cli(a->fd, "Out of memory for context addition\n"); break; case EBUSY: ast_cli(a->fd, "Failed to lock context(s) list, please try again later\n"); break; case EEXIST: ast_cli(a->fd, "Context '%s' already included in '%s' context\n", a->argv[3], a->argv[5]); break; case ENOENT: case EINVAL: ast_cli(a->fd, "There is no existence of context '%s'\n", errno == ENOENT ? a->argv[5] : a->argv[3]); break; default: ast_cli(a->fd, "Failed to include '%s' in '%s' context\n", a->argv[3], a->argv[5]); break; } return CLI_FAILURE; } /* show some info ... */ ast_cli(a->fd, "Context '%s' included in '%s' context\n", a->argv[3], a->argv[5]); return CLI_SUCCESS; } static char *complete_dialplan_add_include(struct ast_cli_args *a) { struct ast_context *c; int which = 0; char *ret = NULL; int len = strlen(a->word); if (a->pos == 3) { /* 'dialplan add include _X_' (context) ... */ if (ast_rdlock_contexts()) { ast_log(LOG_ERROR, "Failed to lock context list\n"); return NULL; } for (c = NULL; !ret && (c = ast_walk_contexts(c)); ) if (partial_match(ast_get_context_name(c), a->word, len) && ++which > a->n) ret = strdup(ast_get_context_name(c)); ast_unlock_contexts(); return ret; } else if (a->pos == 4) { /* dialplan add include CTX _X_ */ /* complete as 'into' if context exists or we are unable to check */ char *context, *dupline; const char *s = skip_words(a->line, 3); /* should not fail */ if (a->n != 0) /* only once */ return NULL; /* parse context from line ... */ context = dupline = strdup(s); if (!context) { ast_log(LOG_ERROR, "Out of free memory\n"); return strdup("into"); } strsep(&dupline, " "); /* check for context existence ... */ if (ast_rdlock_contexts()) { ast_log(LOG_ERROR, "Failed to lock context list\n"); /* our fault, we can't check, so complete 'into' ... */ ret = strdup("into"); } else { struct ast_context *ctx; for (ctx = NULL; !ret && (ctx = ast_walk_contexts(ctx)); ) if (!strcmp(context, ast_get_context_name(ctx))) ret = strdup("into"); /* found */ ast_unlock_contexts(); } free(context); return ret; } else if (a->pos == 5) { /* 'dialplan add include CTX into _X_' (dst context) */ char *context, *dupline, *into; const char *s = skip_words(a->line, 3); /* should not fail */ context = dupline = strdup(s); if (!dupline) { ast_log(LOG_ERROR, "Out of free memory\n"); return NULL; } strsep(&dupline, " "); /* skip context */ into = strsep(&dupline, " "); /* error if missing context or fifth word is not 'into' */ if (!strlen(context) || strcmp(into, "into")) { ast_log(LOG_ERROR, "bad context %s or missing into %s\n", context, into); goto error3; } if (ast_rdlock_contexts()) { ast_log(LOG_ERROR, "Failed to lock context list\n"); goto error3; } for (c = NULL; (c = ast_walk_contexts(c)); ) if (!strcmp(context, ast_get_context_name(c))) break; if (c) { /* first context exists, go on... */ /* go through all contexts ... */ for (c = NULL; !ret && (c = ast_walk_contexts(c)); ) { if (!strcmp(context, ast_get_context_name(c))) continue; /* skip ourselves */ if (partial_match(ast_get_context_name(c), a->word, len) && !lookup_ci(c, context) /* not included yet */ && ++which > a->n) ret = strdup(ast_get_context_name(c)); } } else { ast_log(LOG_ERROR, "context %s not found\n", context); } ast_unlock_contexts(); error3: free(context); return ret; } return NULL; } /*! * \brief 'save dialplan' CLI command implementation functions ... */ static char *handle_cli_dialplan_save(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { char filename[256], overrideswitch[256] = ""; struct ast_context *c; struct ast_config *cfg; struct ast_variable *v; int incomplete = 0; /* incomplete config write? */ FILE *output; struct ast_flags config_flags = { 0 }; const char *base, *slash, *file; switch (cmd) { case CLI_INIT: e->command = "dialplan save"; e->usage = "Usage: dialplan save [/path/to/extension/file]\n" " Save dialplan created by pbx_config module.\n" "\n" "Example: dialplan save (/etc/asterisk/extensions.conf)\n" " dialplan save /home/markster (/home/markster/extensions.conf)\n"; return NULL; case CLI_GENERATE: return NULL; } if (! (static_config && !write_protect_config)) { ast_cli(a->fd, "I can't save dialplan now, see '%s' example file.\n", config); return CLI_FAILURE; } if (a->argc != 2 && a->argc != 3) return CLI_SHOWUSAGE; if (ast_mutex_lock(&save_dialplan_lock)) { ast_cli(a->fd, "Failed to lock dialplan saving (another proccess saving?)\n"); return CLI_FAILURE; } /* XXX the code here is quite loose, a pathname with .conf in it * is assumed to be a complete pathname */ if (a->argc == 3) { /* have config path. Look for *.conf */ base = a->argv[2]; if (!strstr(a->argv[2], ".conf")) { /*no, this is assumed to be a pathname */ /* if filename ends with '/', do not add one */ slash = (*(a->argv[2] + strlen(a->argv[2]) -1) == '/') ? "/" : ""; file = config; /* default: 'extensions.conf' */ } else { /* yes, complete file name */ slash = ""; file = ""; } } else { /* no config file, default one */ base = ast_config_AST_CONFIG_DIR; slash = "/"; file = config; } snprintf(filename, sizeof(filename), "%s%s%s", base, slash, config); cfg = ast_config_load("extensions.conf", config_flags); /* try to lock contexts list */ if (ast_rdlock_contexts()) { ast_cli(a->fd, "Failed to lock contexts list\n"); ast_mutex_unlock(&save_dialplan_lock); ast_config_destroy(cfg); return CLI_FAILURE; } /* create new file ... */ if (!(output = fopen(filename, "wt"))) { ast_cli(a->fd, "Failed to create file '%s'\n", filename); ast_unlock_contexts(); ast_mutex_unlock(&save_dialplan_lock); ast_config_destroy(cfg); return CLI_FAILURE; } /* fireout general info */ if (overrideswitch_config) { snprintf(overrideswitch, sizeof(overrideswitch), "overrideswitch=%s\n", overrideswitch_config); } fprintf(output, "[general]\nstatic=%s\nwriteprotect=%s\nautofallthrough=%s\nclearglobalvars=%s\n%sextenpatternmatchnew=%s\n\n", static_config ? "yes" : "no", write_protect_config ? "yes" : "no", autofallthrough_config ? "yes" : "no", clearglobalvars_config ? "yes" : "no", overrideswitch_config ? overrideswitch : "", extenpatternmatchnew_config ? "yes" : "no"); if ((v = ast_variable_browse(cfg, "globals"))) { fprintf(output, "[globals]\n"); while(v) { fprintf(output, "%s => %s\n", v->name, v->value); v = v->next; } fprintf(output, "\n"); } ast_config_destroy(cfg); #define PUT_CTX_HDR do { \ if (!context_header_written) { \ fprintf(output, "[%s]\n", ast_get_context_name(c)); \ context_header_written = 1; \ } \ } while (0) /* walk all contexts */ for (c = NULL; (c = ast_walk_contexts(c)); ) { int context_header_written = 0; struct ast_exten *ext, *last_written_e = NULL; struct ast_include *i; struct ast_ignorepat *ip; struct ast_sw *sw; /* try to lock context and fireout all info */ if (ast_rdlock_context(c)) { /* lock failure */ incomplete = 1; continue; } /* registered by this module? */ /* XXX do we need this ? */ if (!strcmp(ast_get_context_registrar(c), registrar)) { fprintf(output, "[%s]\n", ast_get_context_name(c)); context_header_written = 1; } /* walk extensions ... */ for (ext = NULL; (ext = ast_walk_context_extensions(c, ext)); ) { struct ast_exten *p = NULL; /* fireout priorities */ while ( (p = ast_walk_extension_priorities(ext, p)) ) { if (strcmp(ast_get_extension_registrar(p), registrar) != 0) /* not this source */ continue; /* make empty line between different extensions */ if (last_written_e != NULL && strcmp(ast_get_extension_name(last_written_e), ast_get_extension_name(p))) fprintf(output, "\n"); last_written_e = p; PUT_CTX_HDR; if (ast_get_extension_priority(p) == PRIORITY_HINT) { /* easy */ fprintf(output, "exten => %s,hint,%s\n", ast_get_extension_name(p), ast_get_extension_app(p)); } else { const char *sep, *cid; const char *el = ast_get_extension_label(p); char label[128] = ""; if (ast_get_extension_matchcid(p)) { sep = "/"; cid = ast_get_extension_cidmatch(p); } else sep = cid = ""; if (el && (snprintf(label, sizeof(label), "(%s)", el) != (strlen(el) + 2))) incomplete = 1; /* error encountered or label > 125 chars */ fprintf(output, "exten => %s%s%s,%d%s,%s(%s)\n", ast_get_extension_name(p), (ast_strlen_zero(sep) ? "" : sep), (ast_strlen_zero(cid) ? "" : cid), ast_get_extension_priority(p), label, ast_get_extension_app(p), (ast_strlen_zero(ast_get_extension_app_data(p)) ? "" : (const char *)ast_get_extension_app_data(p))); } } } /* written any extensions? ok, write space between exten & inc */ if (last_written_e) fprintf(output, "\n"); /* walk through includes */ for (i = NULL; (i = ast_walk_context_includes(c, i)) ; ) { if (strcmp(ast_get_include_registrar(i), registrar) != 0) continue; /* not mine */ PUT_CTX_HDR; fprintf(output, "include => %s\n", ast_get_include_name(i)); } if (ast_walk_context_includes(c, NULL)) fprintf(output, "\n"); /* walk through switches */ for (sw = NULL; (sw = ast_walk_context_switches(c, sw)) ; ) { if (strcmp(ast_get_switch_registrar(sw), registrar) != 0) continue; /* not mine */ PUT_CTX_HDR; fprintf(output, "switch => %s/%s\n", ast_get_switch_name(sw), ast_get_switch_data(sw)); } if (ast_walk_context_switches(c, NULL)) fprintf(output, "\n"); /* fireout ignorepats ... */ for (ip = NULL; (ip = ast_walk_context_ignorepats(c, ip)); ) { if (strcmp(ast_get_ignorepat_registrar(ip), registrar) != 0) continue; /* not mine */ PUT_CTX_HDR; fprintf(output, "ignorepat => %s\n", ast_get_ignorepat_name(ip)); } ast_unlock_context(c); } ast_unlock_contexts(); ast_mutex_unlock(&save_dialplan_lock); fclose(output); if (incomplete) { ast_cli(a->fd, "Saved dialplan is incomplete\n"); return CLI_FAILURE; } ast_cli(a->fd, "Dialplan successfully saved into '%s'\n", filename); return CLI_SUCCESS; } /*! * \brief ADD EXTENSION command stuff */ static char *handle_cli_dialplan_add_extension(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { char *whole_exten; char *exten, *prior; int iprior = -2; char *cidmatch, *app, *app_data; char *start, *end; switch (cmd) { case CLI_INIT: e->command = "dialplan add extension"; e->usage = "Usage: dialplan add extension ,,,\n" " into [replace]\n\n" " This command will add new extension into . If there is an\n" " existence of extension with the same priority and last 'replace'\n" " arguments is given here we simply replace this extension.\n" "\n" "Example: dialplan add extension 6123,1,Dial,IAX/216.207.245.56/6123 into local\n" " Now, you can dial 6123 and talk to Markster :)\n"; return NULL; case CLI_GENERATE: return complete_dialplan_add_extension(a); } /* check for arguments at first */ if (a->argc != 6 && a->argc != 7) return CLI_SHOWUSAGE; if (strcmp(a->argv[4], "into")) return CLI_SHOWUSAGE; if (a->argc == 7) if (strcmp(a->argv[6], "replace")) return CLI_SHOWUSAGE; /* XXX overwrite argv[3] */ whole_exten = a->argv[3]; exten = strsep(&whole_exten,","); if (strchr(exten, '/')) { cidmatch = exten; strsep(&cidmatch,"/"); } else { cidmatch = NULL; } prior = strsep(&whole_exten,","); if (prior) { if (!strcmp(prior, "hint")) { iprior = PRIORITY_HINT; } else { if (sscanf(prior, "%d", &iprior) != 1) { ast_cli(a->fd, "'%s' is not a valid priority\n", prior); prior = NULL; } } } app = whole_exten; if (app && (start = strchr(app, '(')) && (end = strrchr(app, ')'))) { *start = *end = '\0'; app_data = start + 1; } else { if (app) { app_data = strchr(app, ','); if (app_data) { *app_data = '\0'; app_data++; } } else app_data = NULL; } if (!exten || !prior || !app || (!app_data && iprior != PRIORITY_HINT)) return CLI_SHOWUSAGE; if (!app_data) app_data=""; if (ast_add_extension(a->argv[5], a->argc == 7 ? 1 : 0, exten, iprior, NULL, cidmatch, app, (void *)strdup(app_data), ast_free_ptr, registrar)) { switch (errno) { case ENOMEM: ast_cli(a->fd, "Out of free memory\n"); break; case EBUSY: ast_cli(a->fd, "Failed to lock context(s) list, please try again later\n"); break; case ENOENT: ast_cli(a->fd, "No existence of '%s' context\n", a->argv[5]); break; case EEXIST: ast_cli(a->fd, "Extension %s@%s with priority %s already exists\n", exten, a->argv[5], prior); break; default: ast_cli(a->fd, "Failed to add '%s,%s,%s,%s' extension into '%s' context\n", exten, prior, app, app_data, a->argv[5]); break; } return CLI_FAILURE; } if (a->argc == 7) ast_cli(a->fd, "Extension %s@%s (%s) replace by '%s,%s,%s,%s'\n", exten, a->argv[5], prior, exten, prior, app, app_data); else ast_cli(a->fd, "Extension '%s,%s,%s,%s' added into '%s' context\n", exten, prior, app, app_data, a->argv[5]); return CLI_SUCCESS; } /*! dialplan add extension 6123,1,Dial,IAX/212.71.138.13/6123 into local */ static char *complete_dialplan_add_extension(struct ast_cli_args *a) { int which = 0; if (a->pos == 4) { /* complete 'into' word ... */ return (a->n == 0) ? strdup("into") : NULL; } else if (a->pos == 5) { /* complete context */ struct ast_context *c = NULL; int len = strlen(a->word); char *res = NULL; /* try to lock contexts list ... */ if (ast_rdlock_contexts()) { ast_log(LOG_WARNING, "Failed to lock contexts list\n"); return NULL; } /* walk through all contexts */ while ( !res && (c = ast_walk_contexts(c)) ) if (partial_match(ast_get_context_name(c), a->word, len) && ++which > a->n) res = strdup(ast_get_context_name(c)); ast_unlock_contexts(); return res; } else if (a->pos == 6) { return a->n == 0 ? strdup("replace") : NULL; } return NULL; } /*! * IGNOREPAT CLI stuff */ static char *handle_cli_dialplan_add_ignorepat(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { switch (cmd) { case CLI_INIT: e->command = "dialplan add ignorepat"; e->usage = "Usage: dialplan add ignorepat into \n" " This command adds a new ignore pattern into context \n" "\n" "Example: dialplan add ignorepat _3XX into local\n"; return NULL; case CLI_GENERATE: return complete_dialplan_add_ignorepat(a); } if (a->argc != 6) return CLI_SHOWUSAGE; if (strcmp(a->argv[4], "into")) return CLI_SHOWUSAGE; if (ast_context_add_ignorepat(a->argv[5], a->argv[3], registrar)) { switch (errno) { case ENOMEM: ast_cli(a->fd, "Out of free memory\n"); break; case ENOENT: ast_cli(a->fd, "There is no existence of '%s' context\n", a->argv[5]); break; case EEXIST: ast_cli(a->fd, "Ignore pattern '%s' already included in '%s' context\n", a->argv[3], a->argv[5]); break; case EBUSY: ast_cli(a->fd, "Failed to lock context(s) list, please, try again later\n"); break; default: ast_cli(a->fd, "Failed to add ingore pattern '%s' into '%s' context\n", a->argv[3], a->argv[5]); break; } return CLI_FAILURE; } ast_cli(a->fd, "Ignore pattern '%s' added into '%s' context\n", a->argv[3], a->argv[5]); return CLI_SUCCESS; } static char *complete_dialplan_add_ignorepat(struct ast_cli_args *a) { if (a->pos == 4) return a->n == 0 ? strdup("into") : NULL; else if (a->pos == 5) { struct ast_context *c; int which = 0; char *dupline, *ignorepat = NULL; const char *s; char *ret = NULL; int len = strlen(a->word); /* XXX skip first three words 'dialplan' 'add' 'ignorepat' */ s = skip_words(a->line, 3); if (s == NULL) return NULL; dupline = strdup(s); if (!dupline) { ast_log(LOG_ERROR, "Malloc failure\n"); return NULL; } ignorepat = strsep(&dupline, " "); if (ast_rdlock_contexts()) { ast_log(LOG_ERROR, "Failed to lock contexts list\n"); return NULL; } for (c = NULL; !ret && (c = ast_walk_contexts(c));) { int found = 0; if (!partial_match(ast_get_context_name(c), a->word, len)) continue; /* not mine */ if (ignorepat) /* there must be one, right ? */ found = lookup_c_ip(c, ignorepat); if (!found && ++which > a->n) ret = strdup(ast_get_context_name(c)); } if (ignorepat) free(ignorepat); ast_unlock_contexts(); return ret; } return NULL; } static char *handle_cli_dialplan_remove_ignorepat(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { switch (cmd) { case CLI_INIT: e->command = "dialplan remove ignorepat"; e->usage = "Usage: dialplan remove ignorepat from \n" " This command removes an ignore pattern from context \n" "\n" "Example: dialplan remove ignorepat _3XX from local\n"; return NULL; case CLI_GENERATE: return complete_dialplan_remove_ignorepat(a); } if (a->argc != 6) return CLI_SHOWUSAGE; if (strcmp(a->argv[4], "from")) return CLI_SHOWUSAGE; if (ast_context_remove_ignorepat(a->argv[5], a->argv[3], registrar)) { switch (errno) { case EBUSY: ast_cli(a->fd, "Failed to lock context(s) list, please try again later\n"); break; case ENOENT: ast_cli(a->fd, "There is no existence of '%s' context\n", a->argv[5]); break; case EINVAL: ast_cli(a->fd, "There is no existence of '%s' ignore pattern in '%s' context\n", a->argv[3], a->argv[5]); break; default: ast_cli(a->fd, "Failed to remove ignore pattern '%s' from '%s' context\n", a->argv[3], a->argv[5]); break; } return CLI_FAILURE; } ast_cli(a->fd, "Ignore pattern '%s' removed from '%s' context\n", a->argv[3], a->argv[5]); return CLI_SUCCESS; } static char *complete_dialplan_remove_ignorepat(struct ast_cli_args *a) { struct ast_context *c; int which = 0; char *ret = NULL; if (a->pos == 3) { int len = strlen(a->word); if (ast_rdlock_contexts()) { ast_log(LOG_WARNING, "Failed to lock contexts list\n"); return NULL; } for (c = NULL; !ret && (c = ast_walk_contexts(c));) { struct ast_ignorepat *ip; if (ast_rdlock_context(c)) /* error, skip it */ continue; for (ip = NULL; !ret && (ip = ast_walk_context_ignorepats(c, ip));) { if (partial_match(ast_get_ignorepat_name(ip), a->word, len) && ++which > a->n) { /* n-th match */ struct ast_context *cw = NULL; int found = 0; while ( (cw = ast_walk_contexts(cw)) && cw != c && !found) { /* XXX do i stop on c, or skip it ? */ found = lookup_c_ip(cw, ast_get_ignorepat_name(ip)); } if (!found) ret = strdup(ast_get_ignorepat_name(ip)); } } ast_unlock_context(c); } ast_unlock_contexts(); return ret; } else if (a->pos == 4) { return a->n == 0 ? strdup("from") : NULL; } else if (a->pos == 5) { /* XXX check this */ char *dupline, *duplinet, *ignorepat; int len = strlen(a->word); dupline = strdup(a->line); if (!dupline) { ast_log(LOG_WARNING, "Out of free memory\n"); return NULL; } duplinet = dupline; strsep(&duplinet, " "); strsep(&duplinet, " "); ignorepat = strsep(&duplinet, " "); if (!ignorepat) { free(dupline); return NULL; } if (ast_rdlock_contexts()) { ast_log(LOG_WARNING, "Failed to lock contexts list\n"); free(dupline); return NULL; } for (c = NULL; !ret && (c = ast_walk_contexts(c)); ) { if (ast_rdlock_context(c)) /* fail, skip it */ continue; if (!partial_match(ast_get_context_name(c), a->word, len)) continue; if (lookup_c_ip(c, ignorepat) && ++which > a->n) ret = strdup(ast_get_context_name(c)); ast_unlock_context(c); } ast_unlock_contexts(); free(dupline); return NULL; } return NULL; } static int pbx_load_module(void); static char *handle_cli_dialplan_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { switch (cmd) { case CLI_INIT: e->command = "dialplan reload"; e->usage = "Usage: dialplan reload\n" " Reload extensions.conf without reloading any other\n" " modules. This command does not delete global variables\n" " unless clearglobalvars is set to yes in extensions.conf\n"; return NULL; case CLI_GENERATE: return NULL; } if (a->argc != 2) return CLI_SHOWUSAGE; if (clearglobalvars_config) pbx_builtin_clear_globals(); pbx_load_module(); ast_cli(a->fd, "Dialplan reloaded.\n"); return CLI_SUCCESS; } /*! * CLI entries for commands provided by this module */ static struct ast_cli_entry cli_pbx_config[] = { AST_CLI_DEFINE(handle_cli_dialplan_add_extension, "Add new extension into context"), AST_CLI_DEFINE(handle_cli_dialplan_remove_extension, "Remove a specified extension"), AST_CLI_DEFINE(handle_cli_dialplan_add_ignorepat, "Add new ignore pattern"), AST_CLI_DEFINE(handle_cli_dialplan_remove_ignorepat, "Remove ignore pattern from context"), AST_CLI_DEFINE(handle_cli_dialplan_add_include, "Include context in other context"), AST_CLI_DEFINE(handle_cli_dialplan_remove_include, "Remove a specified include from context"), AST_CLI_DEFINE(handle_cli_dialplan_reload, "Reload extensions and *only* extensions") }; static struct ast_cli_entry cli_dialplan_save = AST_CLI_DEFINE(handle_cli_dialplan_save, "Save dialplan"); /*! * Standard module functions ... */ static int unload_module(void) { if (static_config && !write_protect_config) ast_cli_unregister(&cli_dialplan_save); if (overrideswitch_config) { ast_free(overrideswitch_config); } ast_cli_unregister_multiple(cli_pbx_config, sizeof(cli_pbx_config) / sizeof(struct ast_cli_entry)); ast_context_destroy(NULL, registrar); return 0; } static int pbx_load_config(const char *config_file) { struct ast_config *cfg; char *end; char *label; #ifdef LOW_MEMORY char realvalue[256]; #else char realvalue[8192]; #endif int lastpri = -2; struct ast_context *con; struct ast_variable *v; const char *cxt; const char *aft; const char *newpm, *ovsw; struct ast_flags config_flags = { 0 }; cfg = ast_config_load(config_file, config_flags); if (!cfg) return 0; /* Use existing config to populate the PBX table */ static_config = ast_true(ast_variable_retrieve(cfg, "general", "static")); write_protect_config = ast_true(ast_variable_retrieve(cfg, "general", "writeprotect")); if ((aft = ast_variable_retrieve(cfg, "general", "autofallthrough"))) autofallthrough_config = ast_true(aft); if ((newpm = ast_variable_retrieve(cfg, "general", "extenpatternmatchnew"))) extenpatternmatchnew_config = ast_true(newpm); clearglobalvars_config = ast_true(ast_variable_retrieve(cfg, "general", "clearglobalvars")); if ((ovsw = ast_variable_retrieve(cfg, "general", "overrideswitch"))) { if (overrideswitch_config) { ast_free(overrideswitch_config); } if (!ast_strlen_zero(ovsw)) { overrideswitch_config = ast_strdup(ovsw); } else { overrideswitch_config = NULL; } } if ((cxt = ast_variable_retrieve(cfg, "general", "userscontext"))) ast_copy_string(userscontext, cxt, sizeof(userscontext)); else ast_copy_string(userscontext, "default", sizeof(userscontext)); for (v = ast_variable_browse(cfg, "globals"); v; v = v->next) { pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1); pbx_builtin_setvar_helper(NULL, v->name, realvalue); } for (cxt = NULL; (cxt = ast_category_browse(cfg, cxt)); ) { /* All categories but "general" or "globals" are considered contexts */ if (!strcasecmp(cxt, "general") || !strcasecmp(cxt, "globals")) continue; con=ast_context_find_or_create(&local_contexts, local_table, cxt, registrar); if (con == NULL) continue; for (v = ast_variable_browse(cfg, cxt); v; v = v->next) { if (!strcasecmp(v->name, "exten")) { char *tc = ast_strdup(v->value); if (tc) { int ipri = -2; char realext[256]=""; char *plus, *firstp; char *pri, *appl, *data, *cidmatch; char *stringp = tc; char *ext = strsep(&stringp, ","); if (!ext) ext=""; pbx_substitute_variables_helper(NULL, ext, realext, sizeof(realext) - 1); cidmatch = strchr(realext, '/'); if (cidmatch) { *cidmatch++ = '\0'; ast_shrink_phone_number(cidmatch); } pri = strsep(&stringp, ","); if (!pri) pri=""; pri = ast_skip_blanks(pri); pri = ast_trim_blanks(pri); label = strchr(pri, '('); if (label) { *label++ = '\0'; end = strchr(label, ')'); if (end) *end = '\0'; else ast_log(LOG_WARNING, "Label missing trailing ')' at line %d\n", v->lineno); } plus = strchr(pri, '+'); if (plus) *plus++ = '\0'; if (!strcmp(pri,"hint")) ipri=PRIORITY_HINT; else if (!strcmp(pri, "next") || !strcmp(pri, "n")) { if (lastpri > -2) ipri = lastpri + 1; else ast_log(LOG_WARNING, "Can't use 'next' priority on the first entry!\n"); } else if (!strcmp(pri, "same") || !strcmp(pri, "s")) { if (lastpri > -2) ipri = lastpri; else ast_log(LOG_WARNING, "Can't use 'same' priority on the first entry!\n"); } else if (sscanf(pri, "%d", &ipri) != 1 && (ipri = ast_findlabel_extension2(NULL, con, realext, pri, cidmatch)) < 1) { ast_log(LOG_WARNING, "Invalid priority/label '%s' at line %d\n", pri, v->lineno); ipri = 0; } appl = S_OR(stringp, ""); /* Find the first occurrence of '(' */ firstp = strchr(appl, '('); if (!firstp) { /* No arguments */ data = ""; } else { appl = strsep(&stringp, "("); data = stringp; end = strrchr(data, ')'); if ((end = strrchr(data, ')'))) { *end = '\0'; } else { ast_log(LOG_WARNING, "No closing parenthesis found? '%s(%s'\n", appl, data); } } if (!data) data = ""; appl = ast_skip_blanks(appl); if (ipri) { if (plus) ipri += atoi(plus); lastpri = ipri; if (!ast_opt_dont_warn && !strcmp(realext, "_.")) ast_log(LOG_WARNING, "The use of '_.' for an extension is strongly discouraged and can have unexpected behavior. Please use '_X.' instead at line %d\n", v->lineno); if (ast_add_extension2(con, 0, realext, ipri, label, cidmatch, appl, strdup(data), ast_free_ptr, registrar)) { ast_log(LOG_WARNING, "Unable to register extension at line %d\n", v->lineno); } } free(tc); } } else if (!strcasecmp(v->name, "include")) { pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1); if (ast_context_add_include2(con, realvalue, registrar)) ast_log(LOG_WARNING, "Unable to include context '%s' in context '%s'\n", v->value, cxt); } else if (!strcasecmp(v->name, "ignorepat")) { pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1); if (ast_context_add_ignorepat2(con, realvalue, registrar)) ast_log(LOG_WARNING, "Unable to include ignorepat '%s' in context '%s'\n", v->value, cxt); } else if (!strcasecmp(v->name, "switch") || !strcasecmp(v->name, "lswitch") || !strcasecmp(v->name, "eswitch")) { char *stringp = realvalue; char *appl, *data; if (!strcasecmp(v->name, "switch")) pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1); else ast_copy_string(realvalue, v->value, sizeof(realvalue)); appl = strsep(&stringp, "/"); data = S_OR(stringp, ""); if (ast_context_add_switch2(con, appl, data, !strcasecmp(v->name, "eswitch"), registrar)) ast_log(LOG_WARNING, "Unable to include switch '%s' in context '%s'\n", v->value, cxt); } else { ast_log(LOG_WARNING, "==!!== Unknown directive: %s at line %d -- IGNORING!!!\n", v->name, v->lineno); } } } ast_config_destroy(cfg); return 1; } static void append_interface(char *iface, int maxlen, char *add) { int len = strlen(iface); if (strlen(add) + len < maxlen - 2) { if (strlen(iface)) { iface[len] = '&'; strcpy(iface + len + 1, add); } else strcpy(iface, add); } } static void pbx_load_users(void) { struct ast_config *cfg; char *cat, *chan; const char *dahdichan; const char *hasexten, *altexts; char tmp[256]; char iface[256]; char dahdicopy[256]; char *ext, altcopy[256]; char *c; int len; int hasvoicemail; int start, finish, x; struct ast_context *con = NULL; struct ast_flags config_flags = { 0 }; cfg = ast_config_load("users.conf", config_flags); if (!cfg) return; for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { if (!strcasecmp(cat, "general")) continue; iface[0] = '\0'; len = sizeof(iface); if (ast_true(ast_config_option(cfg, cat, "hassip"))) { snprintf(tmp, sizeof(tmp), "SIP/%s", cat); append_interface(iface, sizeof(iface), tmp); } if (ast_true(ast_config_option(cfg, cat, "hasiax"))) { snprintf(tmp, sizeof(tmp), "IAX2/%s", cat); append_interface(iface, sizeof(iface), tmp); } if (ast_true(ast_config_option(cfg, cat, "hash323"))) { snprintf(tmp, sizeof(tmp), "H323/%s", cat); append_interface(iface, sizeof(iface), tmp); } hasexten = ast_config_option(cfg, cat, "hasexten"); if (hasexten && !ast_true(hasexten)) continue; hasvoicemail = ast_true(ast_config_option(cfg, cat, "hasvoicemail")); dahdichan = ast_variable_retrieve(cfg, cat, "dahdichan"); if (!dahdichan) dahdichan = ast_variable_retrieve(cfg, "general", "dahdichan"); if (!ast_strlen_zero(dahdichan)) { ast_copy_string(dahdicopy, dahdichan, sizeof(dahdicopy)); c = dahdicopy; chan = strsep(&c, ","); while (chan) { if (sscanf(chan, "%d-%d", &start, &finish) == 2) { /* Range */ } else if (sscanf(chan, "%d", &start)) { /* Just one */ finish = start; } else { start = 0; finish = 0; } if (finish < start) { x = finish; finish = start; start = x; } for (x = start; x <= finish; x++) { snprintf(tmp, sizeof(tmp), "DAHDI/%d", x); append_interface(iface, sizeof(iface), tmp); } chan = strsep(&c, ","); } } if (!ast_strlen_zero(iface)) { /* Only create a context here when it is really needed. Otherwise default empty context created by pbx_config may conflict with the one explicitly created by pbx_ael */ if (!con) con = ast_context_find_or_create(&local_contexts, local_table, userscontext, registrar); if (!con) { ast_log(LOG_ERROR, "Can't find/create user context '%s'\n", userscontext); return; } /* Add hint */ ast_add_extension2(con, 0, cat, -1, NULL, NULL, iface, NULL, NULL, registrar); /* If voicemail, use "stdexten" else use plain old dial */ if (hasvoicemail) { snprintf(tmp, sizeof(tmp), "stdexten,%s,${HINT}", cat); ast_add_extension2(con, 0, cat, 1, NULL, NULL, "Macro", strdup(tmp), ast_free_ptr, registrar); } else { ast_add_extension2(con, 0, cat, 1, NULL, NULL, "Dial", strdup("${HINT}"), ast_free_ptr, registrar); } altexts = ast_variable_retrieve(cfg, cat, "alternateexts"); if (!ast_strlen_zero(altexts)) { snprintf(tmp, sizeof(tmp), "%s,1", cat); ast_copy_string(altcopy, altexts, sizeof(altcopy)); c = altcopy; ext = strsep(&c, ","); while (ext) { ast_add_extension2(con, 0, ext, 1, NULL, NULL, "Goto", strdup(tmp), ast_free_ptr, registrar); ext = strsep(&c, ","); } } } } ast_config_destroy(cfg); } static int pbx_load_module(void) { struct ast_context *con; if (!local_table) local_table = ast_hashtab_create(17, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0); if (!pbx_load_config(config)) return AST_MODULE_LOAD_DECLINE; pbx_load_users(); ast_merge_contexts_and_delete(&local_contexts, local_table, registrar); local_table = NULL; /* the local table has been moved into the global one. */ local_contexts = NULL; for (con = NULL; (con = ast_walk_contexts(con));) ast_context_verify_includes(con); pbx_set_overrideswitch(overrideswitch_config); pbx_set_autofallthrough(autofallthrough_config); pbx_set_extenpatternmatchnew(extenpatternmatchnew_config); return AST_MODULE_LOAD_SUCCESS; } static int load_module(void) { if (pbx_load_module()) return AST_MODULE_LOAD_DECLINE; if (static_config && !write_protect_config) ast_cli_register(&cli_dialplan_save); ast_cli_register_multiple(cli_pbx_config, sizeof(cli_pbx_config) / sizeof(struct ast_cli_entry)); return AST_MODULE_LOAD_SUCCESS; } static int reload(void) { if (clearglobalvars_config) pbx_builtin_clear_globals(); return pbx_load_module(); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Text Extension Configuration", .load = load_module, .unload = unload_module, .reload = reload, ); asterisk-1.6.1.0/pbx/pbx_realtime.c0000644000175000017500000001716311035031417016357 0ustar maniacmaniac/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 1999 - 2005, Digium, Inc. * * Mark Spencer * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. */ /*! \file * * \brief Realtime PBX Module * * \arg See also: \ref AstARA */ #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision: 129307 $") #include "asterisk/file.h" #include "asterisk/logger.h" #include "asterisk/channel.h" #include "asterisk/config.h" #include "asterisk/pbx.h" #include "asterisk/module.h" #include "asterisk/frame.h" #include "asterisk/term.h" #include "asterisk/manager.h" #include "asterisk/cli.h" #include "asterisk/lock.h" #include "asterisk/md5.h" #include "asterisk/linkedlists.h" #include "asterisk/chanvars.h" #include "asterisk/sched.h" #include "asterisk/io.h" #include "asterisk/utils.h" #include "asterisk/crypto.h" #include "asterisk/astdb.h" #define MODE_MATCH 0 #define MODE_MATCHMORE 1 #define MODE_CANMATCH 2 #define EXT_DATA_SIZE 256 /* Realtime switch looks up extensions in the supplied realtime table. [context@][realtimetable][/options] If the realtimetable is omitted it is assumed to be "extensions". If no context is specified the context is assumed to be whatever is the container. The realtime table should have entries for context,exten,priority,app,args The realtime table currently does not support callerid fields. */ static struct ast_variable *realtime_switch_common(const char *table, const char *context, const char *exten, int priority, int mode) { struct ast_variable *var; struct ast_config *cfg; char pri[20]; char *ematch; char rexten[AST_MAX_EXTENSION + 20]=""; int match; snprintf(pri, sizeof(pri), "%d", priority); switch(mode) { case MODE_MATCHMORE: ematch = "exten LIKE"; snprintf(rexten, sizeof(rexten), "%s_%%", exten); break; case MODE_CANMATCH: ematch = "exten LIKE"; snprintf(rexten, sizeof(rexten), "%s%%", exten); break; case MODE_MATCH: default: ematch = "exten"; ast_copy_string(rexten, exten, sizeof(rexten)); } var = ast_load_realtime(table, ematch, rexten, "context", context, "priority", pri, SENTINEL); if (!var) { cfg = ast_load_realtime_multientry(table, "exten LIKE", "\\_%", "context", context, "priority", pri, SENTINEL); if (cfg) { char *cat = ast_category_browse(cfg, NULL); while(cat) { switch(mode) { case MODE_MATCHMORE: match = ast_extension_close(cat, exten, 1); break; case MODE_CANMATCH: match = ast_extension_close(cat, exten, 0); break; case MODE_MATCH: default: match = ast_extension_match(cat, exten); } if (match) { var = ast_category_detach_variables(ast_category_get(cfg, cat)); break; } cat = ast_category_browse(cfg, cat); } ast_config_destroy(cfg); } } return var; } static struct ast_variable *realtime_common(const char *context, const char *exten, int priority, const char *data, int mode) { const char *ctx = NULL; char *table; struct ast_variable *var=NULL; char *buf = ast_strdupa(data); if (buf) { char *opts = strchr(buf, '/'); if (opts) *opts++ = '\0'; table = strchr(buf, '@'); if (table) { *table++ = '\0'; ctx = buf; } ctx = S_OR(ctx, context); table = S_OR(table, "extensions"); var = realtime_switch_common(table, ctx, exten, priority, mode); } return var; } static int realtime_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) { struct ast_variable *var = realtime_common(context, exten, priority, data, MODE_MATCH); if (var) { ast_variables_destroy(var); return 1; } return 0; } static int realtime_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) { struct ast_variable *var = realtime_common(context, exten, priority, data, MODE_CANMATCH); if (var) { ast_variables_destroy(var); return 1; } return 0; } static int realtime_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) { int res = -1; struct ast_variable *var = realtime_common(context, exten, priority, data, MODE_MATCH); if (var) { char *tmp=""; char *app = NULL; struct ast_variable *v; for (v = var; v ; v = v->next) { if (!strcasecmp(v->name, "app")) app = ast_strdupa(v->value); else if (!strcasecmp(v->name, "appdata")) { if (ast_compat_pbx_realtime) { char *ptr; int in = 0; tmp = alloca(strlen(v->value) * 2 + 1); for (ptr = tmp; *v->value; v->value++) { if (*v->value == ',') { *ptr++ = '\\'; *ptr++ = ','; } else if (*v->value == '|' && !in) { *ptr++ = ','; } else { *ptr++ = *v->value; } /* Don't escape '|', meaning 'or', inside expressions ($[ ]) */ if (v->value[0] == '[' && v->value[-1] == '$') { in++; } else if (v->value[0] == ']' && in) { in--; } } *ptr = '\0'; } else { tmp = ast_strdupa(v->value); } } } ast_variables_destroy(var); if (!ast_strlen_zero(app)) { struct ast_app *a = pbx_findapp(app); if (a) { char appdata[512]; char tmp1[80]; char tmp2[80]; char tmp3[EXT_DATA_SIZE]; appdata[0] = 0; /* just in case the substitute var func isn't called */ if(!ast_strlen_zero(tmp)) pbx_substitute_variables_helper(chan, tmp, appdata, sizeof(appdata) - 1); ast_verb(3, "Executing %s(\"%s\", \"%s\")\n", term_color(tmp1, app, COLOR_BRCYAN, 0, sizeof(tmp1)), term_color(tmp2, chan->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), term_color(tmp3, S_OR(appdata, ""), COLOR_BRMAGENTA, 0, sizeof(tmp3))); manager_event(EVENT_FLAG_DIALPLAN, "Newexten", "Channel: %s\r\n" "Context: %s\r\n" "Extension: %s\r\n" "Priority: %d\r\n" "Application: %s\r\n" "AppData: %s\r\n" "Uniqueid: %s\r\n", chan->name, chan->context, chan->exten, chan->priority, app, !ast_strlen_zero(appdata) ? appdata : "(NULL)", chan->uniqueid); res = pbx_exec(chan, a, appdata); } else ast_log(LOG_NOTICE, "No such application '%s' for extension '%s' in context '%s'\n", app, exten, context); } else { ast_log(LOG_WARNING, "No application specified for realtime extension '%s' in context '%s'\n", exten, context); } } return res; } static int realtime_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) { struct ast_variable *var = realtime_common(context, exten, priority, data, MODE_MATCHMORE); if (var) { ast_variables_destroy(var); return 1; } return 0; } static struct ast_switch realtime_switch = { name: "Realtime", description: "Realtime Dialplan Switch", exists: realtime_exists, canmatch: realtime_canmatch, exec: realtime_exec, matchmore: realtime_matchmore, }; static int unload_module(void) { ast_unregister_switch(&realtime_switch); return 0; } static int load_module(void) { if (ast_register_switch(&realtime_switch)) return AST_MODULE_LOAD_FAILURE; return AST_MODULE_LOAD_SUCCESS; } AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Realtime Switch"); asterisk-1.6.1.0/pbx/pbx_spool.c0000644000175000017500000003702511115542344015715 0ustar maniacmaniac/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 1999 - 2005, Digium, Inc. * * Mark Spencer * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. */ /*! \file * * \brief Full-featured outgoing call spool support * */ #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision: 160561 $") #include #include #include #include #include "asterisk/paths.h" /* use ast_config_AST_SPOOL_DIR */ #include "asterisk/lock.h" #include "asterisk/file.h" #include "asterisk/logger.h" #include "asterisk/channel.h" #include "asterisk/callerid.h" #include "asterisk/pbx.h" #include "asterisk/module.h" #include "asterisk/utils.h" #include "asterisk/options.h" /* * pbx_spool is similar in spirit to qcall, but with substantially enhanced functionality... * The spool file contains a header */ enum { /*! Always delete the call file after a call succeeds or the * maximum number of retries is exceeded, even if the * modification time of the call file is in the future. */ SPOOL_FLAG_ALWAYS_DELETE = (1 << 0), /* Don't unlink the call file after processing, move in qdonedir */ SPOOL_FLAG_ARCHIVE = (1 << 1) }; static char qdir[255]; static char qdonedir[255]; struct outgoing { char fn[256]; int retries; /*!< Current number of retries */ int maxretries; /*!< Maximum number of retries permitted */ int retrytime; /*!< How long to wait between retries (in seconds) */ int waittime; /*!< How long to wait for an answer */ long callingpid; /*!< PID which is currently calling */ int format; /*!< Formats (codecs) for this call */ char tech[256]; /*!< Which channel driver to use for outgoing call */ char dest[256]; /*!< Which device/line to use for outgoing call */ char app[256]; /*!< If application: Application name */ char data[256]; /*!< If applicatoin: Application data */ char exten[AST_MAX_EXTENSION]; /*!< If extension/context/priority: Extension in dialplan */ char context[AST_MAX_CONTEXT]; /*!< If extension/context/priority: Dialplan context */ int priority; /*!< If extension/context/priority: Dialplan priority */ char cid_num[256]; /*!< CallerID Information: Number/extension */ char cid_name[256]; /*!< CallerID Information: Name */ char account[AST_MAX_ACCOUNT_CODE]; /*!< account code */ struct ast_variable *vars; /*!< Variables and Functions */ int maxlen; /*!< Maximum length of call */ struct ast_flags options; /*!< options */ }; static void init_outgoing(struct outgoing *o) { o->priority = 1; o->retrytime = 300; o->waittime = 45; o->format = AST_FORMAT_SLINEAR; ast_set_flag(&o->options, SPOOL_FLAG_ALWAYS_DELETE); } static void free_outgoing(struct outgoing *o) { if (o->vars) { ast_variables_destroy(o->vars); } ast_free(o); } static int apply_outgoing(struct outgoing *o, char *fn, FILE *f) { char buf[256]; char *c, *c2; int lineno = 0; struct ast_variable *var, *last = o->vars; while (last && last->next) { last = last->next; } while(fgets(buf, sizeof(buf), f)) { lineno++; /* Trim comments */ c = buf; while ((c = strchr(c, '#'))) { if ((c == buf) || (*(c-1) == ' ') || (*(c-1) == '\t')) *c = '\0'; else c++; } c = buf; while ((c = strchr(c, ';'))) { if ((c > buf) && (c[-1] == '\\')) { memmove(c - 1, c, strlen(c) + 1); c++; } else { *c = '\0'; break; } } /* Trim trailing white space */ while(!ast_strlen_zero(buf) && buf[strlen(buf) - 1] < 33) buf[strlen(buf) - 1] = '\0'; if (!ast_strlen_zero(buf)) { c = strchr(buf, ':'); if (c) { *c = '\0'; c++; while ((*c) && (*c < 33)) c++; #if 0 printf("'%s' is '%s' at line %d\n", buf, c, lineno); #endif if (!strcasecmp(buf, "channel")) { ast_copy_string(o->tech, c, sizeof(o->tech)); if ((c2 = strchr(o->tech, '/'))) { *c2 = '\0'; c2++; ast_copy_string(o->dest, c2, sizeof(o->dest)); } else { ast_log(LOG_NOTICE, "Channel should be in form Tech/Dest at line %d of %s\n", lineno, fn); o->tech[0] = '\0'; } } else if (!strcasecmp(buf, "callerid")) { ast_callerid_split(c, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num)); } else if (!strcasecmp(buf, "application")) { ast_copy_string(o->app, c, sizeof(o->app)); } else if (!strcasecmp(buf, "data")) { ast_copy_string(o->data, c, sizeof(o->data)); } else if (!strcasecmp(buf, "maxretries")) { if (sscanf(c, "%d", &o->maxretries) != 1) { ast_log(LOG_WARNING, "Invalid max retries at line %d of %s\n", lineno, fn); o->maxretries = 0; } } else if (!strcasecmp(buf, "codecs")) { ast_parse_allow_disallow(NULL, &o->format, c, 1); } else if (!strcasecmp(buf, "context")) { ast_copy_string(o->context, c, sizeof(o->context)); } else if (!strcasecmp(buf, "extension")) { ast_copy_string(o->exten, c, sizeof(o->exten)); } else if (!strcasecmp(buf, "priority")) { if ((sscanf(c, "%d", &o->priority) != 1) || (o->priority < 1)) { ast_log(LOG_WARNING, "Invalid priority at line %d of %s\n", lineno, fn); o->priority = 1; } } else if (!strcasecmp(buf, "retrytime")) { if ((sscanf(c, "%d", &o->retrytime) != 1) || (o->retrytime < 1)) { ast_log(LOG_WARNING, "Invalid retrytime at line %d of %s\n", lineno, fn); o->retrytime = 300; } } else if (!strcasecmp(buf, "waittime")) { if ((sscanf(c, "%d", &o->waittime) != 1) || (o->waittime < 1)) { ast_log(LOG_WARNING, "Invalid waittime at line %d of %s\n", lineno, fn); o->waittime = 45; } } else if (!strcasecmp(buf, "retry")) { o->retries++; } else if (!strcasecmp(buf, "startretry")) { if (sscanf(c, "%ld", &o->callingpid) != 1) { ast_log(LOG_WARNING, "Unable to retrieve calling PID!\n"); o->callingpid = 0; } } else if (!strcasecmp(buf, "endretry") || !strcasecmp(buf, "abortretry")) { o->callingpid = 0; o->retries++; } else if (!strcasecmp(buf, "delayedretry")) { } else if (!strcasecmp(buf, "setvar") || !strcasecmp(buf, "set")) { c2 = c; strsep(&c2, "="); if (c2) { var = ast_variable_new(c, c2, fn); if (var) { /* Always insert at the end, because some people want to treat the spool file as a script */ if (last) { last->next = var; } else { o->vars = var; } last = var; } } else ast_log(LOG_WARNING, "Malformed \"%s\" argument. Should be \"%s: variable=value\"\n", buf, buf); } else if (!strcasecmp(buf, "account")) { ast_copy_string(o->account, c, sizeof(o->account)); } else if (!strcasecmp(buf, "alwaysdelete")) { ast_set2_flag(&o->options, ast_true(c), SPOOL_FLAG_ALWAYS_DELETE); } else if (!strcasecmp(buf, "archive")) { ast_set2_flag(&o->options, ast_true(c), SPOOL_FLAG_ARCHIVE); } else { ast_log(LOG_WARNING, "Unknown keyword '%s' at line %d of %s\n", buf, lineno, fn); } } else ast_log(LOG_NOTICE, "Syntax error at line %d of %s\n", lineno, fn); } } ast_copy_string(o->fn, fn, sizeof(o->fn)); if (ast_strlen_zero(o->tech) || ast_strlen_zero(o->dest) || (ast_strlen_zero(o->app) && ast_strlen_zero(o->exten))) { ast_log(LOG_WARNING, "At least one of app or extension must be specified, along with tech and dest in file %s\n", fn); return -1; } return 0; } static void safe_append(struct outgoing *o, time_t now, char *s) { int fd; FILE *f; struct utimbuf tbuf; if ((fd = open(o->fn, O_WRONLY | O_APPEND)) < 0) return; if ((f = fdopen(fd, "a"))) { fprintf(f, "\n%s: %ld %d (%ld)\n", s, (long)ast_mainpid, o->retries, (long) now); fclose(f); } else close(fd); /* Update the file time */ tbuf.actime = now; tbuf.modtime = now + o->retrytime; if (utime(o->fn, &tbuf)) ast_log(LOG_WARNING, "Unable to set utime on %s: %s\n", o->fn, strerror(errno)); } /*! * \brief Remove a call file from the outgoing queue optionally moving it in the archive dir * * \param o the pointer to outgoing struct * \param status the exit status of the call. Can be "Completed", "Failed" or "Expired" */ static int remove_from_queue(struct outgoing *o, const char *status) { int fd; FILE *f; char newfn[256]; const char *bname; if (!ast_test_flag(&o->options, SPOOL_FLAG_ALWAYS_DELETE)) { struct stat current_file_status; if (!stat(o->fn, ¤t_file_status)) { if (time(NULL) < current_file_status.st_mtime) return 0; } } if (!ast_test_flag(&o->options, SPOOL_FLAG_ARCHIVE)) { unlink(o->fn); return 0; } if (ast_mkdir(qdonedir, 0777)) { ast_log(LOG_WARNING, "Unable to create queue directory %s -- outgoing spool archiving disabled\n", qdonedir); unlink(o->fn); return -1; } if ((fd = open(o->fn, O_WRONLY | O_APPEND))) { if ((f = fdopen(fd, "a"))) { fprintf(f, "Status: %s\n", status); fclose(f); } else close(fd); } if (!(bname = strrchr(o->fn, '/'))) bname = o->fn; else bname++; snprintf(newfn, sizeof(newfn), "%s/%s", qdonedir, bname); /* a existing call file the archive dir is overwritten */ unlink(newfn); if (rename(o->fn, newfn) != 0) { unlink(o->fn); return -1; } else return 0; } static void *attempt_thread(void *data) { struct outgoing *o = data; int res, reason; if (!ast_strlen_zero(o->app)) { ast_verb(3, "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries); res = ast_pbx_outgoing_app(o->tech, o->format, o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL); o->vars = NULL; } else { ast_verb(3, "Attempting call on %s/%s for %s@%s:%d (Retry %d)\n", o->tech, o->dest, o->exten, o->context,o->priority, o->retries); res = ast_pbx_outgoing_exten(o->tech, o->format, o->dest, o->waittime * 1000, o->context, o->exten, o->priority, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL); o->vars = NULL; } if (res) { ast_log(LOG_NOTICE, "Call failed to go through, reason (%d) %s\n", reason, ast_channel_reason2str(reason)); if (o->retries >= o->maxretries + 1) { /* Max retries exceeded */ ast_log(LOG_EVENT, "Queued call to %s/%s expired without completion after %d attempt%s\n", o->tech, o->dest, o->retries - 1, ((o->retries - 1) != 1) ? "s" : ""); remove_from_queue(o, "Expired"); } else { /* Notate that the call is still active */ safe_append(o, time(NULL), "EndRetry"); } } else { ast_log(LOG_NOTICE, "Call completed to %s/%s\n", o->tech, o->dest); ast_log(LOG_EVENT, "Queued call to %s/%s completed\n", o->tech, o->dest); remove_from_queue(o, "Completed"); } free_outgoing(o); return NULL; } static void launch_service(struct outgoing *o) { pthread_t t; int ret; if ((ret = ast_pthread_create_detached(&t, NULL, attempt_thread, o))) { ast_log(LOG_WARNING, "Unable to create thread :( (returned error: %d)\n", ret); free_outgoing(o); } } static int scan_service(char *fn, time_t now, time_t atime) { struct outgoing *o = NULL; FILE *f; int res = 0; if (!(o = ast_calloc(1, sizeof(*o)))) { ast_log(LOG_WARNING, "Out of memory ;(\n"); return -1; } init_outgoing(o); /* Attempt to open the file */ if (!(f = fopen(fn, "r+"))) { remove_from_queue(o, "Failed"); free_outgoing(o); ast_log(LOG_WARNING, "Unable to open %s: %s, deleting\n", fn, strerror(errno)); return -1; } /* Read in and verify the contents */ if (apply_outgoing(o, fn, f)) { remove_from_queue(o, "Failed"); free_outgoing(o); ast_log(LOG_WARNING, "Invalid file contents in %s, deleting\n", fn); fclose(f); return -1; } #if 0 printf("Filename: %s, Retries: %d, max: %d\n", fn, o->retries, o->maxretries); #endif fclose(f); if (o->retries <= o->maxretries) { now += o->retrytime; if (o->callingpid && (o->callingpid == ast_mainpid)) { safe_append(o, time(NULL), "DelayedRetry"); ast_log(LOG_DEBUG, "Delaying retry since we're currently running '%s'\n", o->fn); free_outgoing(o); } else { /* Increment retries */ o->retries++; /* If someone else was calling, they're presumably gone now so abort their retry and continue as we were... */ if (o->callingpid) safe_append(o, time(NULL), "AbortRetry"); safe_append(o, now, "StartRetry"); launch_service(o); } res = now; } else { ast_log(LOG_EVENT, "Queued call to %s/%s expired without completion after %d attempt%s\n", o->tech, o->dest, o->retries - 1, ((o->retries - 1) != 1) ? "s" : ""); remove_from_queue(o, "Expired"); free_outgoing(o); } return res; } static void *scan_thread(void *unused) { struct stat st; DIR *dir; struct dirent *de; char fn[256]; int res; time_t last = 0, next = 0, now; struct timespec ts = { .tv_sec = 1 }; while (!ast_fully_booted) { nanosleep(&ts, NULL); } for(;;) { /* Wait a sec */ nanosleep(&ts, NULL); time(&now); if (stat(qdir, &st)) { ast_log(LOG_WARNING, "Unable to stat %s\n", qdir); continue; } /* Make sure it is time for us to execute our check */ if ((st.st_mtime == last) && (next && (next > now))) continue; #if 0 printf("atime: %ld, mtime: %ld, ctime: %ld\n", st.st_atime, st.st_mtime, st.st_ctime); printf("Ooh, something changed / timeout\n"); #endif next = 0; last = st.st_mtime; if (!(dir = opendir(qdir))) { ast_log(LOG_WARNING, "Unable to open directory %s: %s\n", qdir, strerror(errno)); continue; } while ((de = readdir(dir))) { snprintf(fn, sizeof(fn), "%s/%s", qdir, de->d_name); if (stat(fn, &st)) { ast_log(LOG_WARNING, "Unable to stat %s: %s\n", fn, strerror(errno)); continue; } if (!S_ISREG(st.st_mode)) continue; if (st.st_mtime <= now) { res = scan_service(fn, now, st.st_atime); if (res > 0) { /* Update next service time */ if (!next || (res < next)) { next = res; } } else if (res) { ast_log(LOG_WARNING, "Failed to scan service '%s'\n", fn); } else if (!next) { /* Expired entry: must recheck on the next go-around */ next = st.st_mtime; } } else { /* Update "next" update if necessary */ if (!next || (st.st_mtime < next)) next = st.st_mtime; } } closedir(dir); } return NULL; } static int unload_module(void) { return -1; } static int load_module(void) { pthread_t thread; int ret; snprintf(qdir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "outgoing"); if (ast_mkdir(qdir, 0777)) { ast_log(LOG_WARNING, "Unable to create queue directory %s -- outgoing spool disabled\n", qdir); return AST_MODULE_LOAD_DECLINE; } snprintf(qdonedir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "outgoing_done"); if ((ret = ast_pthread_create_detached_background(&thread, NULL, scan_thread, NULL))) { ast_log(LOG_WARNING, "Unable to create thread :( (returned error: %d)\n", ret); return AST_MODULE_LOAD_FAILURE; } return AST_MODULE_LOAD_SUCCESS; } AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Outgoing Spool Support"); asterisk-1.6.1.0/pbx/dundi-parser.h0000644000175000017500000000615711023474062016313 0ustar maniacmaniac/* * Distributed Universal Number Discovery (DUNDi) * * Copyright (C) 2004 - 2005, Digium Inc. * * Written by Mark Spencer * * This program is Free Software distributed under the terms of * of the GNU General Public License. */ #ifndef _DUNDI_PARSER_H #define _DUNDI_PARSER_H #include "asterisk/dundi.h" #include "asterisk/aes.h" #define DUNDI_MAX_STACK 512 #define DUNDI_MAX_ANSWERS 100 struct dundi_ies { dundi_eid *eids[DUNDI_MAX_STACK + 1]; int eid_direct[DUNDI_MAX_STACK + 1]; dundi_eid *reqeid; int eidcount; char *called_context; char *called_number; struct dundi_answer *answers[DUNDI_MAX_ANSWERS + 1]; struct dundi_hint *hint; int anscount; int ttl; int version; int expiration; int unknowncmd; unsigned char *pubkey; int cause; char *q_dept; char *q_org; char *q_locality; char *q_stateprov; char *q_country; char *q_email; char *q_phone; char *q_ipaddr; char *causestr; unsigned char *encsharedkey; unsigned char *encsig; unsigned long keycrc32; struct dundi_encblock *encblock; int enclen; int cbypass; }; struct dundi_ie_data { int pos; unsigned char buf[8192]; }; /* Choose a different function for output */ extern void dundi_set_output(void (*output)(const char *data)); /* Choose a different function for errors */ extern void dundi_set_error(void (*output)(const char *data)); extern void dundi_showframe(struct dundi_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen); extern const char *dundi_ie2str(int ie); extern int dundi_ie_append_raw(struct dundi_ie_data *ied, unsigned char ie, void *data, int datalen); extern int dundi_ie_append_addr(struct dundi_ie_data *ied, unsigned char ie, struct sockaddr_in *sin); extern int dundi_ie_append_int(struct dundi_ie_data *ied, unsigned char ie, unsigned int value); extern int dundi_ie_append_short(struct dundi_ie_data *ied, unsigned char ie, unsigned short value); extern int dundi_ie_append_str(struct dundi_ie_data *ied, unsigned char ie, char *str); extern int dundi_ie_append_eid(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid); extern int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, char *desc); extern int dundi_ie_append_hint(struct dundi_ie_data *ied, unsigned char ie, unsigned short flags, char *data); extern int dundi_ie_append_answer(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid, unsigned char protocol, unsigned short flags, unsigned short weight, char *desc); extern int dundi_ie_append_encdata(struct dundi_ie_data *ied, unsigned char ie, unsigned char *iv, void *data, int datalen); extern int dundi_ie_append_byte(struct dundi_ie_data *ied, unsigned char ie, unsigned char dat); extern int dundi_ie_append(struct dundi_ie_data *ied, unsigned char ie); extern int dundi_parse_ies(struct dundi_ies *ies, unsigned char *data, int datalen); extern char *dundi_eid_to_str_short(char *s, int maxlen, dundi_eid *eid); extern int dundi_str_short_to_eid(dundi_eid *eid, const char *s); extern int dundi_eid_zero(dundi_eid *eid); extern char *dundi_flags2str(char *s, int maxlen, int flags); extern char *dundi_hint2str(char *s, int maxlen, int flags); #endif asterisk-1.6.1.0/pbx/dundi-parser.c0000644000175000017500000005425511046442607016315 0ustar maniacmaniac/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 1999 - 2005, Digium, Inc. * * Mark Spencer * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. */ /*! \file * * \brief Distributed Universal Number Discovery (DUNDi) * */ #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision: 136298 $") #include #include #include #include "asterisk/frame.h" #include "asterisk/utils.h" #include "asterisk/dundi.h" #include "dundi-parser.h" static void internaloutput(const char *str) { fputs(str, stdout); } static void internalerror(const char *str) { fprintf(stderr, "WARNING: %s", str); } static void (*outputf)(const char *str) = internaloutput; static void (*errorf)(const char *str) = internalerror; char *dundi_eid_to_str_short(char *s, int maxlen, dundi_eid *eid) { int x; char *os = s; if (maxlen < 13) { if (s && (maxlen > 0)) *s = '\0'; } else { for (x=0;x<6;x++) { sprintf(s, "%02X", eid->eid[x]); s += 2; } } return os; } int dundi_str_short_to_eid(dundi_eid *eid, const char *s) { unsigned int eid_int[6]; int x; if (sscanf(s, "%2x%2x%2x%2x%2x%2x", &eid_int[0], &eid_int[1], &eid_int[2], &eid_int[3], &eid_int[4], &eid_int[5]) != 6) return -1; for (x = 0; x < 6; x++) eid->eid[x] = eid_int[x]; return 0; } int dundi_eid_zero(dundi_eid *eid) { int x; for (x = 0; x < ARRAY_LEN(eid->eid); x++) if (eid->eid[x]) return 0; return 1; } static void dump_string(char *output, int maxlen, void *value, int len) { if (maxlen > len + 1) maxlen = len + 1; snprintf(output, maxlen, "%s", (char *) value); } static void dump_cbypass(char *output, int maxlen, void *value, int len) { snprintf(output, maxlen, "Bypass Caches"); } static void dump_eid(char *output, int maxlen, void *value, int len) { if (len == 6) ast_eid_to_str(output, maxlen, (dundi_eid *)value); else snprintf(output, maxlen, "Invalid EID len %d", len); } char *dundi_hint2str(char *buf, int bufsiz, int flags) { strcpy(buf, ""); buf[bufsiz-1] = '\0'; if (flags & DUNDI_HINT_TTL_EXPIRED) { strncat(buf, "TTLEXPIRED|", bufsiz - strlen(buf) - 1); } if (flags & DUNDI_HINT_DONT_ASK) { strncat(buf, "DONTASK|", bufsiz - strlen(buf) - 1); } if (flags & DUNDI_HINT_UNAFFECTED) { strncat(buf, "UNAFFECTED|", bufsiz - strlen(buf) - 1); } /* Get rid of trailing | */ if (ast_strlen_zero(buf)) strcpy(buf, "NONE|"); buf[strlen(buf)-1] = '\0'; return buf; } static void dump_hint(char *output, int maxlen, void *value, int len) { char tmp2[256]; char tmp3[256]; int datalen; struct dundi_hint *hint; if (len < sizeof(*hint)) { snprintf(output, maxlen, ""); return; } hint = (struct dundi_hint *) value;; datalen = len - offsetof(struct dundi_hint, data); if (datalen > sizeof(tmp3) - 1) datalen = sizeof(tmp3) - 1; memcpy(tmp3, hint->data, datalen); tmp3[datalen] = '\0'; dundi_hint2str(tmp2, sizeof(tmp2), ntohs(hint->flags)); if (ast_strlen_zero(tmp3)) snprintf(output, maxlen, "[%s]", tmp2); else snprintf(output, maxlen, "[%s] %s", tmp2, tmp3); } static void dump_cause(char *output, int maxlen, void *value, int len) { static char *causes[] = { "SUCCESS", "GENERAL", "DYNAMIC", "NOAUTH" , }; char tmp2[256]; struct dundi_cause *cause; int datalen; int causecode; if (len < sizeof(*cause)) { snprintf(output, maxlen, ""); return; } cause = (struct dundi_cause*) value; causecode = cause->causecode; datalen = len - offsetof(struct dundi_cause, desc); if (datalen > sizeof(tmp2) - 1) datalen = sizeof(tmp2) - 1; memcpy(tmp2, cause->desc, datalen); tmp2[datalen] = '\0'; if (causecode < ARRAY_LEN(causes)) { if (ast_strlen_zero(tmp2)) snprintf(output, maxlen, "%s", causes[causecode]); else snprintf(output, maxlen, "%s: %s", causes[causecode], tmp2); } else { if (ast_strlen_zero(tmp2)) snprintf(output, maxlen, "%d", causecode); else snprintf(output, maxlen, "%d: %s", causecode, tmp2); } } static void dump_int(char *output, int maxlen, void *value, int len) { if (len == (int)sizeof(unsigned int)) snprintf(output, maxlen, "%lu", (unsigned long)ntohl(*((unsigned int *)value))); else ast_copy_string(output, "Invalid INT", maxlen); } static void dump_short(char *output, int maxlen, void *value, int len) { if (len == (int)sizeof(unsigned short)) snprintf(output, maxlen, "%d", ntohs(*((unsigned short *)value))); else ast_copy_string(output, "Invalid SHORT", maxlen); } static void dump_byte(char *output, int maxlen, void *value, int len) { if (len == (int)sizeof(unsigned char)) snprintf(output, maxlen, "%d", *((unsigned char *)value)); else ast_copy_string(output, "Invalid BYTE", maxlen); } static char *proto2str(int proto, char *buf, int bufsiz) { switch(proto) { case DUNDI_PROTO_NONE: strncpy(buf, "None", bufsiz - 1); break; case DUNDI_PROTO_IAX: strncpy(buf, "IAX", bufsiz - 1); break; case DUNDI_PROTO_SIP: strncpy(buf, "SIP", bufsiz - 1); break; case DUNDI_PROTO_H323: strncpy(buf, "H.323", bufsiz - 1); break; default: snprintf(buf, bufsiz, "Unknown Proto(%d)", proto); } buf[bufsiz-1] = '\0'; return buf; } char *dundi_flags2str(char *buf, int bufsiz, int flags) { strcpy(buf, ""); buf[bufsiz-1] = '\0'; if (flags & DUNDI_FLAG_EXISTS) { strncat(buf, "EXISTS|", bufsiz - strlen(buf) - 1); } if (flags & DUNDI_FLAG_MATCHMORE) { strncat(buf, "MATCHMORE|", bufsiz - strlen(buf) - 1); } if (flags & DUNDI_FLAG_CANMATCH) { strncat(buf, "CANMATCH|", bufsiz - strlen(buf) - 1); } if (flags & DUNDI_FLAG_IGNOREPAT) { strncat(buf, "IGNOREPAT|", bufsiz - strlen(buf) - 1); } if (flags & DUNDI_FLAG_RESIDENTIAL) { strncat(buf, "RESIDENCE|", bufsiz - strlen(buf) - 1); } if (flags & DUNDI_FLAG_COMMERCIAL) { strncat(buf, "COMMERCIAL|", bufsiz - strlen(buf) - 1); } if (flags & DUNDI_FLAG_MOBILE) { strncat(buf, "MOBILE", bufsiz - strlen(buf) - 1); } if (flags & DUNDI_FLAG_NOUNSOLICITED) { strncat(buf, "NOUNSLCTD|", bufsiz - strlen(buf) - 1); } if (flags & DUNDI_FLAG_NOCOMUNSOLICIT) { strncat(buf, "NOCOMUNSLTD|", bufsiz - strlen(buf) - 1); } /* Get rid of trailing | */ if (ast_strlen_zero(buf)) strcpy(buf, "NONE|"); buf[strlen(buf)-1] = '\0'; return buf; } static void dump_answer(char *output, int maxlen, void *value, int len) { struct dundi_answer *answer; char proto[40]; char flags[40]; char eid_str[40]; char tmp[512]=""; int datalen; if (len < sizeof(*answer)) { snprintf(output, maxlen, "Invalid Answer"); return; } answer = (struct dundi_answer *)(value); datalen = len - offsetof(struct dundi_answer, data); if (datalen > sizeof(tmp) - 1) datalen = sizeof(tmp) - 1; memcpy(tmp, answer->data, datalen); tmp[datalen] = '\0'; ast_eid_to_str(eid_str, sizeof(eid_str), &answer->eid); snprintf(output, maxlen, "[%s] %d <%s/%s> from [%s]", dundi_flags2str(flags, sizeof(flags), ntohs(answer->flags)), ntohs(answer->weight), proto2str(answer->protocol, proto, sizeof(proto)), tmp, eid_str); } static void dump_encrypted(char *output, int maxlen, void *value, int len) { char iv[33]; int x; if ((len > 16) && !(len % 16)) { /* Build up IV */ for (x=0;x<16;x++) { snprintf(iv + (x << 1), 3, "%02x", ((unsigned char *)value)[x]); } snprintf(output, maxlen, "[IV %s] %d encrypted blocks\n", iv, len / 16); } else snprintf(output, maxlen, "Invalid Encrypted Datalen %d", len); } static void dump_raw(char *output, int maxlen, void *value, int len) { int x; unsigned char *u = value; output[maxlen - 1] = '\0'; strcpy(output, "[ "); for (x=0;x= 2) { ie = iedata[0]; ielen = iedata[1]; /* Encrypted data is the remainder */ if (ie == DUNDI_IE_ENCDATA) ielen = len - 2; if (ielen + 2> len) { snprintf(tmp, (int)sizeof(tmp), "Total IE length of %d bytes exceeds remaining frame length of %d bytes\n", ielen + 2, len); outputf(tmp); return; } found = 0; for (x = 0; x < ARRAY_LEN(infoelts); x++) { if (infoelts[x].ie == ie) { if (infoelts[x].dump) { infoelts[x].dump(interp, (int)sizeof(interp), iedata + 2, ielen); snprintf(tmp, (int)sizeof(tmp), " %s%-15.15s : %s\n", (spaces ? " " : "" ), infoelts[x].name, interp); outputf(tmp); } else { if (ielen) snprintf(interp, (int)sizeof(interp), "%d bytes", ielen); else strcpy(interp, "Present"); snprintf(tmp, (int)sizeof(tmp), " %s%-15.15s : %s\n", (spaces ? " " : "" ), infoelts[x].name, interp); outputf(tmp); } found++; } } if (!found) { snprintf(tmp, (int)sizeof(tmp), " %sUnknown IE %03d : Present\n", (spaces ? " " : "" ), ie); outputf(tmp); } iedata += (2 + ielen); len -= (2 + ielen); } outputf("\n"); } void dundi_showframe(struct dundi_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen) { char *pref[] = { "Tx", "Rx", " ETx", " Erx" }; char *commands[] = { "ACK ", "DPDISCOVER ", "DPRESPONSE ", "EIDQUERY ", "EIDRESPONSE ", "PRECACHERQ ", "PRECACHERP ", "INVALID ", "UNKNOWN CMD ", "NULL ", "REQREQ ", "REGRESPONSE ", "CANCEL ", "ENCRYPT ", "ENCREJ " }; char class2[20]; char *class; char subclass2[20]; char *subclass; char tmp[256]; char retries[20]; if (ntohs(fhi->dtrans) & DUNDI_FLAG_RETRANS) strcpy(retries, "Yes"); else strcpy(retries, "No"); if ((ntohs(fhi->strans) & DUNDI_FLAG_RESERVED)) { /* Ignore frames with high bit set to 1 */ return; } if ((fhi->cmdresp & 0x3f) > (int)sizeof(commands)/(int)sizeof(char *)) { snprintf(class2, (int)sizeof(class2), "(%d?)", fhi->cmdresp); class = class2; } else { class = commands[(int)(fhi->cmdresp & 0x3f)]; } snprintf(subclass2, (int)sizeof(subclass2), "%02x", fhi->cmdflags); subclass = subclass2; snprintf(tmp, (int)sizeof(tmp), "%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s (%s)\n", pref[rx], retries, fhi->oseqno, fhi->iseqno, class, fhi->cmdresp & 0x40 ? "Response" : "Command"); outputf(tmp); snprintf(tmp, (int)sizeof(tmp), "%s Flags: %s STrans: %5.5d DTrans: %5.5d [%s:%d]%s\n", (rx > 1) ? " " : "", subclass, ntohs(fhi->strans) & ~DUNDI_FLAG_RESERVED, ntohs(fhi->dtrans) & ~DUNDI_FLAG_RETRANS, ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), fhi->cmdresp & 0x80 ? " (Final)" : ""); outputf(tmp); dump_ies(fhi->ies, rx > 1, datalen); } int dundi_ie_append_raw(struct dundi_ie_data *ied, unsigned char ie, void *data, int datalen) { char tmp[256]; if (datalen > ((int)sizeof(ied->buf) - ied->pos)) { snprintf(tmp, (int)sizeof(tmp), "Out of space for ie '%s' (%d), need %d have %d\n", dundi_ie2str(ie), ie, datalen, (int)sizeof(ied->buf) - ied->pos); errorf(tmp); return -1; } ied->buf[ied->pos++] = ie; ied->buf[ied->pos++] = datalen; memcpy(ied->buf + ied->pos, data, datalen); ied->pos += datalen; return 0; } int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, char *data) { char tmp[256]; int datalen = data ? strlen(data) + 1 : 1; if (datalen > ((int)sizeof(ied->buf) - ied->pos)) { snprintf(tmp, (int)sizeof(tmp), "Out of space for ie '%s' (%d), need %d have %d\n", dundi_ie2str(ie), ie, datalen, (int)sizeof(ied->buf) - ied->pos); errorf(tmp); return -1; } ied->buf[ied->pos++] = ie; ied->buf[ied->pos++] = datalen; ied->buf[ied->pos++] = cause; memcpy(ied->buf + ied->pos, data, datalen-1); ied->pos += datalen-1; return 0; } int dundi_ie_append_hint(struct dundi_ie_data *ied, unsigned char ie, unsigned short flags, char *data) { char tmp[256]; int datalen = data ? strlen(data) + 2 : 2; if (datalen > ((int)sizeof(ied->buf) - ied->pos)) { snprintf(tmp, (int)sizeof(tmp), "Out of space for ie '%s' (%d), need %d have %d\n", dundi_ie2str(ie), ie, datalen, (int)sizeof(ied->buf) - ied->pos); errorf(tmp); return -1; } ied->buf[ied->pos++] = ie; ied->buf[ied->pos++] = datalen; flags = htons(flags); memcpy(ied->buf + ied->pos, &flags, sizeof(flags)); ied->pos += 2; memcpy(ied->buf + ied->pos, data, datalen-1); ied->pos += datalen-2; return 0; } int dundi_ie_append_encdata(struct dundi_ie_data *ied, unsigned char ie, unsigned char *iv, void *data, int datalen) { char tmp[256]; datalen += 16; if (datalen > ((int)sizeof(ied->buf) - ied->pos)) { snprintf(tmp, (int)sizeof(tmp), "Out of space for ie '%s' (%d), need %d have %d\n", dundi_ie2str(ie), ie, datalen, (int)sizeof(ied->buf) - ied->pos); errorf(tmp); return -1; } ied->buf[ied->pos++] = ie; ied->buf[ied->pos++] = datalen; memcpy(ied->buf + ied->pos, iv, 16); ied->pos += 16; if (data) { memcpy(ied->buf + ied->pos, data, datalen-16); ied->pos += datalen-16; } return 0; } int dundi_ie_append_answer(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid, unsigned char protocol, unsigned short flags, unsigned short weight, char *data) { char tmp[256]; int datalen = data ? strlen(data) + 11 : 11; int x; unsigned short myw; if (datalen > ((int)sizeof(ied->buf) - ied->pos)) { snprintf(tmp, (int)sizeof(tmp), "Out of space for ie '%s' (%d), need %d have %d\n", dundi_ie2str(ie), ie, datalen, (int)sizeof(ied->buf) - ied->pos); errorf(tmp); return -1; } ied->buf[ied->pos++] = ie; ied->buf[ied->pos++] = datalen; for (x=0;x<6;x++) ied->buf[ied->pos++] = eid->eid[x]; ied->buf[ied->pos++] = protocol; myw = htons(flags); memcpy(ied->buf + ied->pos, &myw, 2); ied->pos += 2; myw = htons(weight); memcpy(ied->buf + ied->pos, &myw, 2); ied->pos += 2; memcpy(ied->buf + ied->pos, data, datalen-11); ied->pos += datalen-11; return 0; } int dundi_ie_append_addr(struct dundi_ie_data *ied, unsigned char ie, struct sockaddr_in *sin) { return dundi_ie_append_raw(ied, ie, sin, (int)sizeof(struct sockaddr_in)); } int dundi_ie_append_int(struct dundi_ie_data *ied, unsigned char ie, unsigned int value) { unsigned int newval; newval = htonl(value); return dundi_ie_append_raw(ied, ie, &newval, (int)sizeof(newval)); } int dundi_ie_append_short(struct dundi_ie_data *ied, unsigned char ie, unsigned short value) { unsigned short newval; newval = htons(value); return dundi_ie_append_raw(ied, ie, &newval, (int)sizeof(newval)); } int dundi_ie_append_str(struct dundi_ie_data *ied, unsigned char ie, char *str) { return dundi_ie_append_raw(ied, ie, str, strlen(str)); } int dundi_ie_append_eid(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid) { return dundi_ie_append_raw(ied, ie, (unsigned char *)eid, sizeof(dundi_eid)); } int dundi_ie_append_byte(struct dundi_ie_data *ied, unsigned char ie, unsigned char dat) { return dundi_ie_append_raw(ied, ie, &dat, 1); } int dundi_ie_append(struct dundi_ie_data *ied, unsigned char ie) { return dundi_ie_append_raw(ied, ie, NULL, 0); } void dundi_set_output(void (*func)(const char *)) { outputf = func; } void dundi_set_error(void (*func)(const char *)) { errorf = func; } int dundi_parse_ies(struct dundi_ies *ies, unsigned char *data, int datalen) { /* Parse data into information elements */ int len; int ie; char tmp[256]; memset(ies, 0, (int)sizeof(struct dundi_ies)); ies->ttl = -1; ies->expiration = -1; ies->unknowncmd = -1; ies->cause = -1; while(datalen >= 2) { ie = data[0]; len = data[1]; if (len > datalen - 2) { errorf("Information element length exceeds message size\n"); return -1; } switch(ie) { case DUNDI_IE_EID: case DUNDI_IE_EID_DIRECT: if (len != (int)sizeof(dundi_eid)) { errorf("Improper entity identifer, expecting 6 bytes!\n"); } else if (ies->eidcount < DUNDI_MAX_STACK) { ies->eids[ies->eidcount] = (dundi_eid *)(data + 2); ies->eid_direct[ies->eidcount] = (ie == DUNDI_IE_EID_DIRECT); ies->eidcount++; } else errorf("Too many entities in stack!\n"); break; case DUNDI_IE_REQEID: if (len != (int)sizeof(dundi_eid)) { errorf("Improper requested entity identifer, expecting 6 bytes!\n"); } else ies->reqeid = (dundi_eid *)(data + 2); break; case DUNDI_IE_CALLED_CONTEXT: ies->called_context = (char *)data + 2; break; case DUNDI_IE_CALLED_NUMBER: ies->called_number = (char *)data + 2; break; case DUNDI_IE_ANSWER: if (len < sizeof(struct dundi_answer)) { snprintf(tmp, (int)sizeof(tmp), "Answer expected to be >=%d bytes long but was %d\n", (int)sizeof(struct dundi_answer), len); errorf(tmp); } else { if (ies->anscount < DUNDI_MAX_ANSWERS) ies->answers[ies->anscount++]= (struct dundi_answer *)(data + 2); else errorf("Ignoring extra answers!\n"); } break; case DUNDI_IE_TTL: if (len != (int)sizeof(unsigned short)) { snprintf(tmp, (int)sizeof(tmp), "Expecting ttl to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len); errorf(tmp); } else ies->ttl = ntohs(*((unsigned short *)(data + 2))); break; case DUNDI_IE_VERSION: if (len != (int)sizeof(unsigned short)) { snprintf(tmp, (int)sizeof(tmp), "Expecting version to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len); errorf(tmp); } else ies->version = ntohs(*((unsigned short *)(data + 2))); break; case DUNDI_IE_EXPIRATION: if (len != (int)sizeof(unsigned short)) { snprintf(tmp, (int)sizeof(tmp), "Expecting expiration to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len); errorf(tmp); } else ies->expiration = ntohs(*((unsigned short *)(data + 2))); break; case DUNDI_IE_KEYCRC32: if (len != (int)sizeof(unsigned int)) { snprintf(tmp, (int)sizeof(tmp), "Expecting expiration to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len); errorf(tmp); } else ies->keycrc32 = ntohl(*((unsigned int *)(data + 2))); break; case DUNDI_IE_UNKNOWN: if (len == 1) ies->unknowncmd = data[2]; else { snprintf(tmp, (int)sizeof(tmp), "Expected single byte Unknown command, but was %d long\n", len); errorf(tmp); } break; case DUNDI_IE_CAUSE: if (len >= 1) { ies->cause = data[2]; ies->causestr = (char *)data + 3; } else { snprintf(tmp, (int)sizeof(tmp), "Expected at least one byte cause, but was %d long\n", len); errorf(tmp); } break; case DUNDI_IE_HINT: if (len >= 2) { ies->hint = (struct dundi_hint *)(data + 2); } else { snprintf(tmp, (int)sizeof(tmp), "Expected at least two byte hint, but was %d long\n", len); errorf(tmp); } break; case DUNDI_IE_DEPARTMENT: ies->q_dept = (char *)data + 2; break; case DUNDI_IE_ORGANIZATION: ies->q_org = (char *)data + 2; break; case DUNDI_IE_LOCALITY: ies->q_locality = (char *)data + 2; break; case DUNDI_IE_STATE_PROV: ies->q_stateprov = (char *)data + 2; break; case DUNDI_IE_COUNTRY: ies->q_country = (char *)data + 2; break; case DUNDI_IE_EMAIL: ies->q_email = (char *)data + 2; break; case DUNDI_IE_PHONE: ies->q_phone = (char *)data + 2; break; case DUNDI_IE_IPADDR: ies->q_ipaddr = (char *)data + 2; break; case DUNDI_IE_ENCDATA: /* Recalculate len as the remainder of the message, regardless of theoretical length */ len = datalen - 2; if ((len > 16) && !(len % 16)) { ies->encblock = (struct dundi_encblock *)(data + 2); ies->enclen = len - 16; } else { snprintf(tmp, (int)sizeof(tmp), "Invalid encrypted data length %d\n", len); errorf(tmp); } break; case DUNDI_IE_SHAREDKEY: if (len == 128) { ies->encsharedkey = (unsigned char *)(data + 2); } else { snprintf(tmp, (int)sizeof(tmp), "Invalid encrypted shared key length %d\n", len); errorf(tmp); } break; case DUNDI_IE_SIGNATURE: if (len == 128) { ies->encsig = (unsigned char *)(data + 2); } else { snprintf(tmp, (int)sizeof(tmp), "Invalid encrypted signature length %d\n", len); errorf(tmp); } break; case DUNDI_IE_CACHEBYPASS: ies->cbypass = 1; break; default: snprintf(tmp, (int)sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", dundi_ie2str(ie), ie, len); outputf(tmp); } /* Overwrite information element with 0, to null terminate previous portion */ data[0] = 0; datalen -= (len + 2); data += (len + 2); } /* Null-terminate last field */ *data = '\0'; if (datalen) { errorf("Invalid information element contents, strange boundary\n"); return -1; } return 0; } asterisk-1.6.1.0/pbx/pbx_loopback.c0000644000175000017500000001350011021344273016340 0ustar maniacmaniac/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 1999 - 2005, Digium, Inc. * * Mark Spencer * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. */ /*! \file * * \brief Loopback PBX Module * */ #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision: 120227 $") #include "asterisk/file.h" #include "asterisk/logger.h" #include "asterisk/channel.h" #include "asterisk/config.h" #include "asterisk/pbx.h" #include "asterisk/module.h" #include "asterisk/frame.h" #include "asterisk/cli.h" #include "asterisk/lock.h" #include "asterisk/md5.h" #include "asterisk/linkedlists.h" #include "asterisk/chanvars.h" #include "asterisk/sched.h" #include "asterisk/io.h" #include "asterisk/utils.h" #include "asterisk/crypto.h" #include "asterisk/astdb.h" /* Loopback switch creates a 'tunnel' to another context. When extension lookups pass through the 'tunnel', Asterisk expressions can be used to modify the target extension, context, and priority in any way desired. If there is a match at the far end, execution jumps through the 'tunnel' to the matched context, extension, and priority. Global variables as well as ${CONTEXT}, ${EXTEN}, and ${PRIORITY} are available for substitution. After substitution Loopback expects to get a string of the form: [exten]@context[:priority][/extramatch] Where exten, context, and priority are another extension, context, and priority to lookup and "extramatch" is a dialplan extension pattern which the *original* number must match. If exten or priority are empty, the original values are used. Note that the search context MUST be a different context from the current context or the search will not succeed. This is intended to reduce the likelihood of loops (they're still possible if you try hard, so be careful!) */ #define LOOPBACK_COMMON \ char buf[1024]; \ int res; \ char *newexten=(char *)exten, *newcontext=(char *)context; \ int newpriority=priority; \ char *newpattern=NULL; \ loopback_subst(buf, sizeof(buf), exten, context, priority, data); \ loopback_parse(&newexten, &newcontext, &newpriority, &newpattern, buf); \ ast_log(LOG_DEBUG, "Parsed into %s @ %s priority %d\n", newexten, newcontext, newpriority); \ if (!strcasecmp(newcontext, context)) return -1 static char *loopback_subst(char *buf, int buflen, const char *exten, const char *context, int priority, const char *data) { struct ast_var_t *newvariable; struct varshead headp; char tmp[80]; snprintf(tmp, sizeof(tmp), "%d", priority); AST_LIST_HEAD_INIT_NOLOCK(&headp); newvariable = ast_var_assign("EXTEN", exten); AST_LIST_INSERT_HEAD(&headp, newvariable, entries); newvariable = ast_var_assign("CONTEXT", context); AST_LIST_INSERT_HEAD(&headp, newvariable, entries); newvariable = ast_var_assign("PRIORITY", tmp); AST_LIST_INSERT_HEAD(&headp, newvariable, entries); /* Substitute variables */ pbx_substitute_variables_varshead(&headp, data, buf, buflen); /* free the list */ while ((newvariable = AST_LIST_REMOVE_HEAD(&headp, entries))) ast_var_delete(newvariable); return buf; } static void loopback_parse(char **newexten, char **newcontext, int *priority, char **newpattern, char *buf) { char *con; char *pri; *newpattern = strchr(buf, '/'); if (*newpattern) *(*newpattern)++ = '\0'; con = strchr(buf, '@'); if (con) { *con++ = '\0'; pri = strchr(con, ':'); } else pri = strchr(buf, ':'); if (!ast_strlen_zero(buf)) *newexten = buf; if (!ast_strlen_zero(con)) *newcontext = con; if (!ast_strlen_zero(pri)) sscanf(pri, "%d", priority); } static int loopback_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) { LOOPBACK_COMMON; res = ast_exists_extension(chan, newcontext, newexten, newpriority, callerid); if (newpattern && !ast_extension_match(newpattern, exten)) res = 0; return res; } static int loopback_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) { LOOPBACK_COMMON; res = ast_canmatch_extension(chan, newcontext, newexten, newpriority, callerid); if (newpattern && !ast_extension_match(newpattern, exten)) res = 0; return res; } static int loopback_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) { int found; LOOPBACK_COMMON; res = ast_spawn_extension(chan, newcontext, newexten, newpriority, callerid, &found, 0); return res; } static int loopback_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) { LOOPBACK_COMMON; res = ast_matchmore_extension(chan, newcontext, newexten, newpriority, callerid); if (newpattern && !ast_extension_match(newpattern, exten)) res = 0; return res; } static struct ast_switch loopback_switch = { name: "Loopback", description: "Loopback Dialplan Switch", exists: loopback_exists, canmatch: loopback_canmatch, exec: loopback_exec, matchmore: loopback_matchmore, }; static int unload_module(void) { ast_unregister_switch(&loopback_switch); return 0; } static int load_module(void) { if (ast_register_switch(&loopback_switch)) return AST_MODULE_LOAD_FAILURE; return AST_MODULE_LOAD_SUCCESS; } AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Loopback Switch"); asterisk-1.6.1.0/pbx/ael/0000755000175000017500000000000011175405517014304 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/0000755000175000017500000000000011175405520016014 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-test140000644000175000017500000000207010723063404020373 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:113 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:pbx_ael.c line:126 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:3 file:pval.c line:2284 func: check_switch_expr Warning: file ./extensions.ael, line 13-13: A default case was automatically added to the switch. LOG: lev:4 file:pval.c line:1071 func: check_continue Error: file ./extensions.ael, line 15-15: 'continue' not in 'for' or 'while' statement! LOG: lev:4 file:pval.c line:1052 func: check_break Error: file ./extensions.ael, line 17-17: 'break' not in switch, for, or while statement! LOG: lev:4 file:pbx_ael.c line:139 func: pbx_load_module Sorry, but 0 syntax errors and 2 semantic errors were detected. It doesn't make sense to compile. LOG: lev:4 file:ael2_parse line:531 func: main 0 contexts, 0 extensions, 0 priorities asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-vtest250000644000175000017500000000031311060072241020553 0ustar maniacmaniac [test11] exten => 841,1,Gosub(test234,s,1("testing", ${CUT(EXTEN,,3)})) exten => 841,2,Goto(${DB(uri/${uri_string})},1) exten => 841,3,Set(line=${DB(uri/${uri_string})}) exten => 841,4,Goto(${line},1) asterisk-1.6.1.0/pbx/ael/ael-test/ael-vtest17/0000755000175000017500000000000011175405520020070 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-vtest17/extensions.ael0000644000175000017500000000324410513753041022754 0ustar maniacmaniaccontext dialextens { /* 101 thru 123, 149 thru 152 */ _10X => Dial(Zap/${EXTEN:2},30,tw); _1ZX => Dial(Zap/${EXTEN:1},30,tw); } /* Due to extenal wiring: dialing 125 will ring 101 dialing 126 will ring 102 and so on until dialing 147 will ring 123 We can dial out on zap 69 thru 72; and 25-47 */ context dialthrus { /* 369-372; 325-347 */ _3XX => Dial(Zap/${EXTEN:1},30,tw); } context t1incoming { includes { dialextens; parkedcalls; } s => { Answer(); Background(welcome-to-test-machine); } } context t1extension { includes { dialextens; dialthrus; } } context incoming { includes { dialextens; parkedcalls; } s => { Answer(); Background(welcome-to-test-machine); } } context extension { includes { dialextens; dialthrus; } 5 => { Record(recording:gsm); Background(recording); } 81 => { iterations=1000000; Set(time1=${EPOCH}); for(i=1; ${i}<${iterations}; i=${i}+1) { NoOp(Hello); } Set(time2=${EPOCH}); Verbose(The time diff is $[${time2} - ${time1} ] seconds); Verbose(Which means that the priorities/sec = $[4* ${iterations} / (${time2} - ${time1}) ]); SayNumber($[4 * ${iterations} / (${time2} - ${time1}) ]); } 82 => { &ndeep(100000); Verbose(Finished 100000 levels deep call!); } 83 => { switch (${EXTEN}) { pattern 8X: Verbose(do something to prepare it); pattern 9X: Verbose(handle both 8x and 9x calls); pattern [4-7]X: Verbose(and this too!); } } } macro ndeep(level) { if( ${level} == 0) { Verbose(2|Got to Level 0); return; } &ndeep($[${level}-1]); return; } asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-ntest240000644000175000017500000001115411003201536020545 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -n option if you aren't interested in seeing all the instructions generated by the compiler) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:115 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:pbx_ael.c line:128 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:131 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. Executed ast_context_find_or_create(conts, name=test11, registrar=pbx_ael); Executed ast_add_extension2(context=test11, rep=0, exten=_X., priority=1, label=(null), callerid=(null), appl=Answer, data=, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test11, rep=0, exten=_X., priority=2, label=(null), callerid=(null), appl=Dial, data=iax2/test11:nosecret@192.168.134.2522, 15,tTwW, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test11, rep=0, exten=_X., priority=3, label=(null), callerid=(null), appl=Hangup, data=, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test11, rep=0, exten=_X., priority=4, label=(null), callerid=(null), appl=NoOp, data=$[{GROUP_COUNT(${target_num}@agent_queue_b)}=1], FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test11, rep=0, exten=_X., priority=5, label=(null), callerid=(null), appl=NoOp, data=$[1+0~~${DB(skip_group/${target_num}/agent_queue_b)}], FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test11, rep=0, exten=_X., priority=6, label=(null), callerid=(null), appl=NoOp, data=$[0~~${DB(skip_group/${target_num}/agent_queue_b)}+1], FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test11, rep=0, exten=_X., priority=7, label=(null), callerid=(null), appl=NoOp, data=$[${GROUP_COUNT(${target_num}@agent_queue_b)}=1+0~~${DB(skip_group/${target_num}/agent_queue_b)}], FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test11, rep=0, exten=_X., priority=8, label=(null), callerid=(null), appl=NoOp, data=$[${GROUP_COUNT(${target_num}@agent_queue_b)}=0~~${DB(skip_group/${target_num}/agent_queue_b)}+1], FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test11, rep=0, exten=_X., priority=9, label=(null), callerid=(null), appl=GotoIf, data=$[${GROUP_COUNT(${target_num}@agent_queue_b)}==1+0~~${DB(skip_group/${target_num}/agent_queue_b)}]?10:11, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test11, rep=0, exten=_X., priority=10, label=(null), callerid=(null), appl=Set, data=testif=$[1+0~~${DB(skip_group/${target_num}/agent_queue_b)}], FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test11, rep=0, exten=_X., priority=11, label=(null), callerid=(null), appl=NoOp, data=Finish if-test11-1, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test11, rep=0, exten=_X., priority=12, label=(null), callerid=(null), appl=GotoIf, data=$[${GROUP_COUNT(${target_num}@agent_queue_b)}==0~~${DB(skip_group/${target_num}/agent_queue_b)}+1]?13:14, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test11, rep=0, exten=_X., priority=13, label=(null), callerid=(null), appl=Set, data=testif=$[1+0~~${DB(skip_group/${target_num}/agent_queue_b)}], FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test11, rep=0, exten=_X., priority=14, label=(null), callerid=(null), appl=NoOp, data=Finish if-test11-2, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test11, rep=0, exten=_X., priority=15, label=(null), callerid=(null), appl=GotoIf, data=$[${GROUP_COUNT(${target_num}@agent_queue_b)}==1+0~~${DB(skip_group/${target_num}/agent_queue_b)}]?16:17, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test11, rep=0, exten=_X., priority=16, label=(null), callerid=(null), appl=Set, data=testif=$[1+0~~${DB(skip_group/${target_num}/agent_queue_b)}], FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test11, rep=0, exten=_X., priority=17, label=(null), callerid=(null), appl=NoOp, data=Finish if-test11-3, FREE, registrar=pbx_ael); LOG: lev:2 file:pbx_ael.c line:134 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. Executed ast_merge_contexts_and_delete(); LOG: lev:2 file:pbx_ael.c line:139 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. Executed ast_walk_contexts(); LOG: lev:2 file:pbx_ael.c line:142 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. LOG: lev:4 file:ael2_parse line:548 func: main 1 contexts, 1 extensions, 17 priorities asterisk-1.6.1.0/pbx/ael/ael-test/setref0000755000175000017500000000015310423206707017232 0ustar maniacmaniac#!/bin/bash for i in res.*; do refname=`echo $i | sed 's/^res/ref/'` echo $refname mv $i $refname done asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-test190000644000175000017500000000426711046713743020421 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:115 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:pbx_ael.c line:128 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:3 file:pval.c line:2313 func: check_context_names Warning: file ./extensions.ael, line 49-62: The context name (incoming) is also declared in file ./extensions.ael, line 62-69! (and neither is marked 'extend') LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 71-175: The macro std-priv-exten does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:2297 func: check_switch_expr Warning: file ./extensions.ael, line 245-246: A default case was automatically added to the switch. LOG: lev:3 file:pval.c line:2439 func: check_pval_item Warning: file ./extensions.ael, line 312-312: macro call to non-existent funcA! (Not even in the extensions.conf stuff!) LOG: lev:3 file:pval.c line:2439 func: check_pval_item Warning: file ./extensions.ael, line 313-313: macro call to non-existent funcD! (Not even in the extensions.conf stuff!) LOG: lev:3 file:pval.c line:1346 func: check_goto Warning: file ./extensions.ael, line 319-319: goto: Couldn't find goto target test5|s|1, not even in extensions.conf! LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 363-366: The macro dialoutpstn does not end with a return; I will insert one. LOG: lev:2 file:pbx_ael.c line:131 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:134 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:139 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:142 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. LOG: lev:4 file:ael2_parse line:518 func: main 13 contexts, 57 extensions, 190 priorities asterisk-1.6.1.0/pbx/ael/ael-test/ael-vtest13/0000755000175000017500000000000011175405520020064 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-vtest13/telemarket_torture.ael20000755000175000017500000006660410466233565024603 0ustar maniacmaniac// // AN EXCERSIZE IN BAD DIALPLAN DESIGN // (What better testing ground than on telemarketers?) // // BAD DESIGN: long, boring introductions followed by long, drawn out menus of choices. // if they survive to the last option, how will they remember the choices? // // BAD DESIGN: Amateur Recording. Poor voice quality, too quiet. // Also, the announcer is definitely not vocally gifted. // Also, the long pauses and clicks between the intro // and menu choices might lead some to think that // the announcements are over, and hang up. Too bad! // WORSE DESIGN: Instead of using the Background application, the Playback // application is used. After taking so much time and trouble // to record this material, the caller must listen and enjoy // every syllable before they can make an option choice. None // of that interrupting with a choice. We want them to savour // every word! // GOOD/BAD, ER INSIDIOUS -- DANGLE A CARROT-- GIVE THE LISTENER A GOOD REASON TO // HANG ON AND VOLUNTARILY LISTEN TO THE TORTURE. // BUT, DON'T MAKE PROMISES YOU WON'T KEEP! context telemarket { s => { begin: Playback(telemarketer-intro); // ; Script: // Due to the extremely high volume of calls from everything from telemarketers // to Septic System Bacteria vendors, we are asking all such organizations // to remove this number from their call list, or as need be, to add this // number to their No-Call list, whichever is relevent. // [THE CARROT:] // We HAVE made some exceptions, and if you wish to see if your organization // has been exempted, please listen to and follow the following prompts. // // Otherwise, please Cease calling this number! // Playback(telemarketer-choices); // if you represent a charitable organization, please dial 1, // if you represent a political organization, please dial 2. // if you represent a polling company, please dial 3, // if you represent a market research organization, please dial 4. // if you represent a magazine or newsletter, please dial 5. // if you represent a commercial organization, please dial 6. } 1 => goto telemarket-charity|s|begin; 2 => goto telemarket-political|s|begin; 3 => goto telemarket-pollster|s|begin; 4 => goto telemarket-research|s|begin; 5 => goto telemarket-magazine|s|begin; 6 => goto telemarket-commercial|s|begin; 7 => goto telemarket-other|s|begin; t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemarket-charity { s => { begin: Playback(telemark-charity-intro); // We have contributed generously to many worthy causes in the past, and will // continue to do so in the future. But we suspect that such organizatons // have sold our name and phone number to each other until we are now hounded // day and night by literally hundreds of such organizations. // Enough is Enough! // // If we have contributed to your cause in the past, we may, perhaps, be disposed to // do so in the future, at our option, // we give no pledges nor make any commitments here. // Send us material via the post if you feel this necessary // but do not even consider email. Any email or further phone calls from your organization // in the future, will be considered an act of aggression, and we will // blacklist your organization for the rest of our natural lives. // // To see if your organization is exempt from these prohibitions, please // comply with the following options. Playback(telemark-charity-choices); // If your organization is disease or genetic defect related, dial 1, // If your organization is handicap related, dial 2. // If your organization is a police or fireman or other similar support entity, please dial 3. // If your organization is a grade school to high school related // fund raiser or other type of activity, please dial 4. // If your organization is a college or univerity or alumnis organization, please dial 5. // If your organization is animal rights or ecology related organization, please dial 6. // If your organization is a political action or candidate support related, please dial 7. // If your organization is a substance abuse related organization or cause, please dial 8. // And any other charity or tax exempt organization should dial 9. } 1 => goto telemarket-char-disease|s|begin; 2 => goto telemarket-char-handicap|s|begin; 3 => goto telemarket-char-police|s|begin; 4 => goto telemarket-char-school|s|begin; 5 => goto telemarket-char-college|s|begin; 6 => goto telemarket-char-animal|s|begin; 7 => goto telemarket-char-candidate|s|begin; 8 => goto telemarket-char-abuse|s|begin; 9 => goto telemarket-char-other|s|begin; // BAD DESIGN: referring all timeouts,invalid choices, etc, back to the root of the menu tree will frustrate users no end! // WORSE DESIGN: How about having the user have to push a button to repeat the current menu? When a time out could just // automatically do it for the user? t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemarket-char-disease { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-char-handicap { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-char-police { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-char-school { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-char-college { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-char-animal { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-char-candidate { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-char-abuse { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-char-other { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-sorry { s => { begin: Playback(telemarket-sorry); // Sorry -- your organization is not exempt. Please stop calling us. // Thank you. goodbye. Hangup(); } } // BAD DESIGN: Hanging up on your audience, no matter what the outcome, is not a nice thing to do! context telemarket-exception { s => { begin: Playback(telemarket-success); // Congratulations. Your organization IS exempt. Please call us back, // but this time, just act like a normal caller. Thank you. Goodbye. Hangup(); } } // BAD DESIGN: Making long cascading menu choices is a nasty thing to do to callers! // BAD DESIGN: Putting the most frequently encountered items at the end of a list is also a nasty thing to do! // GOOD DESIGN: All rejection notices use a single context. All Acceptance also. To change a rejection to an // acceptance, just change the reference from telemarket-sorry to telemarket-exception context telemarket-political { s => { begin: Playback(telemark-polit-intro); // To see if your organization is exempt from our prohibitions, // please follow the following prompts. // please note that they are not in alphabetical order, and you will have to // give them your full attention. Playback(telemark-polit-choices); // if You represent the America First Party, dial 1. // if You represent the American Party, dial 2. // if You represent the American Heritage Party, dial 3. // if You represent the American Independent Party, dial 4. // if You represent the American Nazi Party, dial 5. // if You represent the Pot Party, dial 6. // if You represent the American Reform Party, dial 7. // if You represent the Christian Falenqist Party of America, dial 8. // all others, please dial 9. } 1 => goto telemarket-poli-Am1st|s|begin; 2 => goto telemarket-poli-American|s|begin; 3 => goto telemarket-poli-AmHer|s|begin; 4 => goto telemarket-poli-AmInd|s|begin; 5 => goto telemarket-poli-AmNaz|s|begin; 6 => goto telemarket-poli-Pot|s|begin; 7 => goto telemarket-poli-AmRef|s|begin; 8 => goto telemarket-poli-CFP|s|begin; 9 => goto telemarket-political2|s|begin; t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemarket-political2 { s => { begin: Playback(telemark-politx-intro); // Thank you for your patience, and I congratulate you for your persistence. // Just a few more options! // Playback(telemark-polit2-choices); // if You represent the Communist Party USA, dial 1. // if You represent the Constitution Party, dial 2. // if You represent the Family Values Party, dial 3. // if You represent the Freedom Socialist Party, dial 4. // if You represent the Grass Roots Party, dial 5. // if You represent the Green Party, dial 6. // if You represent the Greens Party, dial 7. // if You represent the Independence Party, dial 8. // all others, goto 9. } 1 => goto telemarket-poli-Communist|s|begin; 2 => goto telemarket-poli-Constit|s|begin; 3 => goto telemarket-poli-FamVal|s|begin; 4 => goto telemarket-poli-FreedSoc|s|begin; 5 => goto telemarket-poli-Grassroot|s|begin; 6 => goto telemarket-poli-Green|s|begin; 7 => goto telemarket-poli-Greens|s|begin; 8 => goto telemarket-poli-Independence|s|begin; 9 => goto telemarket-political3|s|begin; t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemarket-political3 { s => { begin: Playback(telemark-politx-intro); Playback(telemark-polit3-choices); // if You represent the Independant American Party, dial 1. // if You represent the Labor Party, dial 2. // if You represent the Libertarian Party, dial 3. // if You represent the Light Party, dial 4. // if You represent the Natural Law Party, dial 5. // if You represent the New Party, dial 6. // if You represent the New Union Party, dial 7. // if You represent the Peace and Freedom Party, dial 8. // all others, hang on, dial 9. } 1 => goto telemarket-poli-IndAm|s|begin; 2 => goto telemarket-poli-Labor|s|begin; 3 => goto telemarket-poli-Liber|s|begin; 4 => goto telemarket-poli-Light|s|begin; 5 => goto telemarket-poli-NatLaw|s|begin; 6 => goto telemarket-poli-New|s|begin; 7 => goto telemarket-poli-NewUn|s|begin; 8 => goto telemarket-poli-PeaceFree|s|begin; 9 => goto telemarket-political4|s|begin; t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemarket-political4 { s => { begin: Playback(telemark-politx-intro); Playback(telemark-polit4-choices); // if You represent the Prohibition Party, dial 1. // if You represent the Reform Party, dial 2. // if You represent the Revolution , dial 3. // if You represent the Socialist Party USA, dial 4. // if You represent the Socialist Action Party, dial 5. // if You represent the Socialist Equality Party, dial 6. // if You represent the Socialist Labor Party, dial 7. // if You represent the Socialist Workers Party, dial 8. // all others, hang on, and dial 9. } 1 => goto telemarket-poli-Prohib|s|begin; 2 => goto telemarket-poli-Ref|s|begin; 3 => goto telemarket-poli-Revol|s|begin; 4 => goto telemarket-poli-SocPart|s|begin; 5 => goto telemarket-poli-SocAct|s|begin; 6 => goto telemarket-poli-SocEq|s|begin; 7 => goto telemarket-poli-SocLab|s|begin; 8 => goto telemarket-poli-SocWork|s|begin; 9 => goto telemarket-political5|s|begin; t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemarket-political5 { s => { begin: Playback(telemark-politx-intro); Playback(telemark-polit5-choices); // if You represent the Southern Party, dial 1. // if You represent the Southern Independence Party, dial 2. // if You represent the US Pacifist Party, dial 3. // if You represent the We the People Party, dial 4. // if You represent the Workers World Party, dial 5. // if You represent the Democratic Party, dial 6. // if You represent the Republican Party, dial 7. // all others, may dial 8. } 1 => goto telemarket-poli-South|s|begin; 2 => goto telemarket-poli-SoInd|s|begin; 3 => goto telemarket-poli-USPac|s|begin; 4 => goto telemarket-poli-WTP|s|begin; 5 => goto telemarket-poli-WWP|s|begin; 6 => goto telemarket-poli-Democrat|s|begin; 7 => goto telemarket-poli-Repub|s|begin; 8 => goto telemarket-poli-other|s|begin; t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemarket-poli-other { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Repub { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Democrat { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-WWP { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-WTP { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-USPac { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-SoInd { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-South { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-SocWork { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-SocLab { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-SocEq { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-SocAct { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-SocPart { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Revol { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Ref { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Prohib { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-PeaceFree { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-NewUn { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-New { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-NatLaw { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Light { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Liber { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Labor { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-IndAm { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Independence { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Greens { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Green { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Grassroot { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-FreedSoc { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-FamVal { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Constit { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Communist { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-CFP { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-AmRef { s => { begin: goto telemarket-sorry|s|begin; } } // BAD DESIGN: Putting in infinite loops in the menus, whether by design or mistake is not nice! context telemarket-poli-Pot { s => { begin: goto telemarket-political|s|begin; // will the Pot Party Guys even notice an infinite loop? } } context telemarket-poli-AmNaz { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-AmInd { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-AmHer { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-American { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Am1st { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-pollster { s => { begin: Playback(telemark-poll-intro); // I'm sorry-- We are just not available for doing any polling at the moment. So, // please remove us from your list. goto telemarket-sorry|s|begin; } t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemarket-research { s => { begin: Playback(telemark-research-intro); // I'd like to say I'd love to help you with your market survey, but that would be a complete // and total lie. I am not interested in helping you with Market Surveys. // // Please remove me from your call list. It just doesn't pay enough. But Thank you. goto telemarket-sorry|s|begin; } t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemarket-magazine { s => { begin: Playback(telemark-mag-choices); // If you are calling to see if I would like a NEW free subscription // to your magazine or newsletter, please dial 1. // If you are calling to see if I want to Renew an existing subscription, please dial 2. // If you are representing some publisher, and want my opinion about something, or are doing // some kind of survey, please dial 3. // If you are calling to verify that some previous caller actually called me, and the // verification information is correct, please dial 4. // and if your call purpose doesn't match any of the above, please dial 5. } 1 => goto telemark-mag-new|s|begin; 2 => goto telemark-mag-renew|s|begin; 3 => goto telemark-mag-survey|s|begin; 4 => goto telemark-mag-verify|s|begin; 5 => goto telemark-mag-other|s|begin; t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemark-mag-new { s => { begin: Playback(telemark-mag-new); // I'm sorry, I'm maxed out, and the answer is NO. // If you really think I'd LOVE to add your publication to the pile I already get, // Send something via the post. Don't call me. // Thank you. bye. Hangup(); } t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemark-mag-renew { s => { begin: Playback(telemark-mag-renew); // So, you want to see if I want to Renew, do you? The answer is most likely "YES". // // But, I will not answer a long list of questions over the phone. Send such // categorization info via the post, and stop bothering me over the phone, // if this is what you want. // Do you need verification information? Normally I opt out of such nonsense, if possible. // If not, use whatever of the following you can: // My birth month is October. // My birthplace is Kigali, in Rwanda, in Afica. // My eye color is orange. // All of these are wonderfully false, but I use them regularly for such purposes. Thank you. Hangup(); } t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemark-mag-survey { s => { begin: Playback(telemark-mag-survey); // Sorry, I don't have time to answer survey or opinion questions. Find someone // else to help build your marketing database, I guess. Good Luck. Hangup(); } t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemark-mag-verify { s => { begin: Playback(telemark-mag-verify); // If you are calling to verify that your own agents aren't ripping you off, // sorry, I can't help you. I opt out whenever I can, mainly because I'm not // paid enough for this kind of thing. I always lie, and I can't remember // what I might have said. Sorry. Goodbye. Hangup(); } t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemark-mag-other { s => { begin: goto telemarket-sorry|s|begin; } } // BAD DESIGN: Is it entrapment, when you lure telemarketers to reveal their contact information, // Just so you can report them to the FTC/FCC? If it is, isn't it unethical for them // to hide their CID (via Anonymous, usually), to hide their identities from the public? // BTW -- What telemarketer would be stupid enough to fall for this? I'll bet not a single one! // For that matter, what telemarketer will be stupid enough to even enter any of this? I'll bet not a single one! // (but it was fun messing around). context telemarket-commercial { s => { begin: Playback(telemark-comm-intro); // Script: Please leave your name, organization, and phone number, plus // a short description of the purpose of your call, at the prompt. // We will do our best to respond to your call! And, in the mean time, // do not forget to add us to your no-call list! Voicemail(u82); goto telemarket-sorry|s|begin; } t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemarket-other { s => { begin: Playback(telemark-other-intro); // Please review the previous menu options, and see if you really don't // fit in one of the previous categories. // If you do not, go ahead, and call me again, and let me know what category // I should have included in the above list. I appreciate this. Thank you much! Hangup(); } t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } asterisk-1.6.1.0/pbx/ael/ael-test/ael-vtest13/include2.ael20000644000175000017500000000014210466233565022345 0ustar maniacmaniac NoOp(This was included from include2.ael2); #include "include3.ael2" #include "include4.ael2" asterisk-1.6.1.0/pbx/ael/ael-test/ael-vtest13/include1.ael20000644000175000017500000000011610466233565022345 0ustar maniacmaniac NoOp(Hello, this is included from include1.ael2); #include "include2.ael2" asterisk-1.6.1.0/pbx/ael/ael-test/ael-vtest13/include4.ael20000644000175000017500000000012710466233565022352 0ustar maniacmaniac NoOp(This is include4.ael2! Isn't it cool!?!?!?!); NoOp(4 doesn't include anything); asterisk-1.6.1.0/pbx/ael/ael-test/ael-vtest13/include3.ael20000644000175000017500000000007110466233565022347 0ustar maniacmaniac NoOp(This is include3.ael2!); #include "include5.ael2" asterisk-1.6.1.0/pbx/ael/ael-test/ael-vtest13/include5.ael20000644000175000017500000000007010466233565022350 0ustar maniacmaniac NoOp(Include5.ael2 doesn't include anything, either!); asterisk-1.6.1.0/pbx/ael/ael-test/ael-vtest13/extensions.ael0000755000175000017500000022240610722651651022764 0ustar maniacmaniacglobals { static=yes; writeprotect=yes; CONSOLE=Console/dsp; // Console interface for demo IAXINFO=murf:tlhfckoct; // IAXtel username/password FWDNUMBER=544788 ; // your calling number FWDCIDNAME="Joe-Worker"; // your caller id FWDPASSWORD=zingledoodle ; // your password FWDRINGS=Zap/6 ; // the phone to ring FWDVMBOX=1 ; // the VM box for this user } macro std-exten( ext , dev ) { Dial(${dev}/${ext},20); switch(${DIALSTATUS}) { case BUSY: Voicemail(b${ext}); break; case NOANSWER: Voicemail(u${ext}); break; case ANSWER: break; default: Voicemail(u${ext}); } catch a { VoiceMailMain(${ext}); } } macro std-priv-exten_1( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_2( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_3( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_4( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_5( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_6( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_7( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_8( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_9( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_10( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_11( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_12( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_13( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_14( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_15( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_16( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_17( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_18( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_19( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_20( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_21( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_22( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_23( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_24( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_25( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_26( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_27( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_28( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_29( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_30( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_31( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_32( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_33( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_34( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_35( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_36( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_37( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_38( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_39( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_40( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_41( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_42( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_43( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_44( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_45( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_46( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_47( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_48( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_49( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_50( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_51( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_52( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_53( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_54( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_55( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_56( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_57( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_58( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_59( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_60( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_61( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_62( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_63( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_64( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_65( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_66( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_67( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_68( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_69( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_70( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_71( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_72( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_73( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro fillcidname() { if( "${CALLERID(num)}" = "" ) // nothing to work with, quit!!! return; Set(cidn=${DB(cidname/${CALLERID(num)})}); if( "${CALLERID(name)}" != "" ) { if( ("${cidn}" = "Privacy Manager" & "${CALLERID(name)}" != "Privacy Manager") | "${cidn}" = "" ) // if the entry isn't in the database, // or if an entry exists, and it's "Privacy Manager", empty, (or add other useless possibilities). { Set(DB(cidname/${CALLERID(num)})=${CALLERID(name)}); // then set or override what's in the DB } } // Now, we fill in the callerid info from the incoming entry, if it's stuff worth using // Ignore fundamentally semi-anonymous information from local cell phones // if the db has an entry for this number, and it's not a canned string from a cell phone company if( ( "${cidn}" != "" ) & ( "${CALLERID(name)}" = "" | "${CALLERID(name)}" = "CODY,WY " | "${CALLERID(name)}" = "POWELL,WY " | "${CALLERID(name)}" = "WIRELESS CALLER" | "${CALLERID(name)}" = "SUBSCRIBER,WIRE" | "${CALLERID(name)}" = "CELLULAR ONE" | "${CALLERID(name)}" = "Cellular One Customer" | "${CALLERID(name)}" = "CELLULAR ONE " | "${CALLERID(name)}" = "Privacy Manager" | "${CALLERID(name)}" = "RIVERTON,WY " | "${CALLERID(name)}" = "BASIN,WY " | "${CALLERID(name)}" = "BILLINGS,MT " | "${CALLERID(name)}" = "PROVO,UT " | "${CALLERID(name)}" = "TOLL FREE " ) ) // put stuff in the above, that the phone company tends to put in your callerid, // that you would rather override with DB info // there's no way to guess them all, but you can get the most popular ones... // why cell phones can't do CID like everybody else, ....? { Set(CALLERID(name)=${cidn}); // Override what the phone company provides with what's in the DB for this number. } } macro ciddial(dialnum, lookup, waittime, dialopts, ddev) { Set(cidnu=${CALLERID(num)}); Set(cidn=${DB(cidname/${lookup})}); Set(CALLERID(name)=${cidn}); Dial(${ddev}/${dialnum}|${waittime}|${dialopts}); if( "${DIALSTATUS}" = "CHANUNAVAIL" ) { BackGround(try_voip); CALLERID(num)=7075679201; Dial(SIP/1${lookup}@tctwest,${waittime},${dialopts}); if( "${DIALSTATUS}" = "CHANUNAVAIL" ) { BackGround(try_cell); CALLERID(num)=${cidnu}; // put the original number back Dial(Zap/2/${lookup},${waittime},${dialopts}); } } } macro ciddial3(dialnum, lookup, waittime, dialopts, ddev) { Set(cidnu=${CALLERID(num)}); Set(cidn=${DB(cidname/${lookup})}); Set(CALLERID(name)=${cidn}); Dial(${ddev}/${dialnum}|${waittime}|${dialopts}); if( "${DIALSTATUS}" = "CHANUNAVAIL" ) { BackGround(try_cell); Dial(Zap/2/${lookup},${waittime},${dialopts}); } } macro ciddial2(dialnum, lookup, waittime, dialopts, ddev) // give priority to tctwest, then the ZAP in emergencies { Set(cidn=${DB(cidname/${lookup})}); Set(cidnu=${CALLERID(num)}); Set(CALLERID(name)=${cidn}); Set(CALLERID(num)=7075679201); Dial(SIP/1${lookup}@tctwest,${waittime},${dialopts}); if( "${DIALSTATUS}" = "CHANUNAVAIL" ) { Set(CALLERID(num)=${cidnu}); // put the original number back BackGround(try_zap); Dial(${ddev}/${dialnum},${waittime}|${dialopts}); if( "${DIALSTATUS}" = "CHANUNAVAIL" ) { BackGround(try_cell); Dial(Zap/2/${lookup},${waittime},${dialopts}); } } } macro callerid-liar() { TrySystem(/usr/bin/play /var/lib/asterisk/sounds/priv-callerintros/LIAR.gsm&); Background(priv-liar); // Script: OOOps! Sorry! I don't allow men with ski masks pulled over their // faces to get in the front door, and unidentified callers won't fair // any better. You entered *MY* phone number. That won't work. // If you are telemarketing, cross me off the list, and don't call again. // If you did this by mistake, forgive my defenses, and call again. // Alternate: (priv-liar2) // Script: You have chosen to try to deceive my system and withold your CallerID, // by entering my own phone number as YOUR CallerID. I find this // offensive because you are being dishonest. I will not do business nor // waste my time talking to anyone who is less than honest and forthcoming. // Take me off your call list and do not call me again. Hangup(); } macro callerid-bad() { mycid=${CALLERID(num)}:"1([0-9]+)"; Set(CALLERID(num)=${mycid}); Wait(0); } context privacyManagerFailed { s => { begin: Background(PrivManInstructions); // Script: OOps, that didn't go well. You need to enter *your* area code, and *your* 7 digit // phone number, for a total of 10 digits, or you'll be handed over to the monkeys. Let's // try this again, and hopefully you can get past our front-line defenses! PrivacyManager(); if( "${PRIVACYMGRSTATUS}" = "FAILED" ) { Background(tt-allbusy); Background(tt-somethingwrong); Background(tt-monkeysintro); Background(tt-monkeys); Background(tt-weasels); Hangup(); } else { goto homeline|s|postPriv; } } } // Some comments // Some more comments context homeline { s => { begin: Answer(); Set(repeatcount=0); Zapateller(nocallerid); PrivacyManager(); if( "${PRIVACYMGRSTATUS}" = "FAILED" ) { TrySystem(/usr/bin/play /var/lib/asterisk/sounds/privmanfailed.gsm); &std-priv-exten(Zap/3r1&Zap/5r1,2,25,mtw,telemarket,telemarket); Hangup(); return; // goto privacyManagerFailed|s|begin; } postPriv: &fillcidname(); Set(CONFCIDNA=${CALLERID(name)}); Set(CONFCIDNU=${CALLERID(num)}); AGI(callall); AGI(submit-announce.agi); if( "${CALLERID(num)}" : "1" ) { &callerid-bad(); } if( "${CALLERID(num)}" = "7077577685" & "${CALLERID(name)}" : "Privacy Manager" ) { &callerid-liar(); } TrySystem(/usr/local/bin/who-is-it ${CALLERID(num)} "${CALLERID(name)}"&); Set(lds=${DB(playlds/${CALLERID(num)})}); if( "${lds}" = "1" ) { SetMusicOnHold(mohlds); } direct=${DB(DirectCall/${CALLERID(num)})}; if( "${direct}" != "" & ${direct} != 0 ) { verbose(direct is XXX#${direct}XXXX); Playback(greetings/direct); // Welcome to the Murphy residence. This system will automatically try to connect you to... Playback(/var/spool/asterisk/voicemail/default/${direct}/greet); TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/${direct}/greet.wav&); switch(${direct}) { case 1: //Steve &std-priv-exten(Zap/6r3&Sip/murf,1,25,mpA(beep)tw,telemarket,telemarket); goto s|loopback; case 2: //Sonya &std-priv-exten(Zap/3r1&Zap/5r1,2,25,mtw,telemarket,telemarket); goto s|loopback; default: // all the kids Set(z=${direct}-2); goto homeline-kids|${z}|1; } } loopback: ifTime(*|*|20-25|dec) { Playback(greetings/christmas); } else ifTime(*|*|31|dec) { Playback(greetings/newyear); } else ifTime(*|*|1|jan) { Playback(greetings/newyear); } else ifTime(*|*|14|feb) { Playback(greetings/valentines); } else ifTime(*|*|17|mar) { Playback(greetings/stPat); } else ifTime(*|*|31|oct) { Playback(greetings/halloween); } else ifTime(*|mon|15-21|jan) { Playback(greetings/mlkDay); } else ifTime(*|thu|22-28|nov) { Playback(greetings/thanksgiving); } else ifTime(*|mon|25-31|may) { Playback(greetings/memorial); } else ifTime(*|mon|1-7|sep) { Playback(greetings/labor); } else ifTime(*|mon|15-21|feb) { Playback(greetings/president); } else ifTime(*|sun|8-14|may) { Playback(greetings/mothers); } else ifTime(*|sun|15-21|jun) { Playback(greetings/fathers); } else { Playback(greetings/hello); // None of the above? Just a plain hello will do } Background(murphy-homeline-intro1); // Script: Hello-- Welcome to the Murphy's! If you already know what // option you want, you don't have to wait for this entire spiel-- just // have at it. // If you are calling because this number is on a list of some sort, dial 6. // If you want Sonya, dial 1. // If you want one of the kids, dial 2. // If you want Steve, dial 3. // to play with your introduction, dial 5. // If we don't seem to be giving you the time of day, try 7. // Have a good day! } 1 => { // Sonya TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/2/greet.wav&); &std-priv-exten(Zap/3r1&Zap/5r1,2,25,mtw,telemarket,telemarket); goto s|loopback; } 2 => { // Kids goto homeline-kids|s|begin; } 21 => { Dial(IAX2/seaniax,20,T); } 3 => { // Steve &std-priv-exten(Zap/6r3&Sip/murf,1,25,mpA(beep)tw,telemarket,telemarket); goto s|loopback; } 4 => { // Voicemail VoicemailMain(); goto s|loopback; } 5 => { // play with intro goto home-introduction|s|begin; } 6 => { // Telemarketers goto telemarket|s|begin; } 7 => { // time of day, riddle agi(tts-riddle.agi); Background(gsm/what-time-it-is2); SayUnixTime(); goto s|loopback; } 792 => { // Page All goto pageall|s|begin; } 793 => { // check the tone recognition Read(zz,,0,,1,0); SayDigits(${zz}); } t => { Set(repeatcount=${repeatcount} + 1); if( ${repeatcount} < 3 ) { goto s|loopback; // just loopback isn't enough } Hangup(); } i => { Background(invalid); goto s|loopback; } o => { Congestion(); } fax => { Dial(Zap/4); } } // Some comments // Some more comments context pageall { s => { begin: AGI(callall); MeetMe(5555,dtqp); MeetMeAdmin(5555,K); Hangup(); } h => { begin: MeetMeAdmin(5555,K); Background(conf-muted); Hangup(); } } // Some comments // Some more comments context add-to-conference { start => { NoCDR(); MeetMe(5555,dmqp); } h => { Hangup(); } } context home-introduction { s => { begin: Background(intro-options); // Script: To hear your Introduction, dial 1. // to record a new introduction, dial 2. // to return to the main menu, dial 3. // to hear what this is all about, dial 4. } 1 => { Playback(priv-callerintros/${CALLERID(num)}); goto s|begin; } 2 => { goto home-introduction-record|s|begin; } 3 => { goto homeline|s|loopback; } 4 => { Playback(intro-intro); // Script: // This may seem a little strange, but it really is a neat // thing, both for you and for us. I've taped a short introduction // for many of the folks who normally call us. Using the Caller ID // from each incoming call, the system plays the introduction // for that phone number over a speaker, just as the call comes in. // This helps the folks // here in the house more quickly determine who is calling. // and gets the right ones to gravitate to the phone. // You can listen to, and record a new intro for your phone number // using this menu. goto s|begin; } t => { goto s|begin; } i => { Background(invalid); goto s|begin; } o => { goto s|begin; } } context home-introduction-record { s => { begin: Background(intro-record-choices); // Script: // If you want some advice about recording your // introduction, dial 1. // otherwise, dial 2, and introduce yourself after // the beep. } 1 => { Playback(intro-record); // Your introduction should be short and sweet and crisp. // Your introduction will be limited to 10 seconds. // This is NOT meant to be a voice mail message, so // please, don't say anything about why you are calling. // After we are done making the recording, your introduction // will be saved for playback. // If you are the only person that would call from this number, // please state your name. Otherwise, state your business // or residence name instead. For instance, if you are // friend of the family, say, Olie McPherson, and both // you and your kids might call here a lot, you might // say: "This is the distinguished Olie McPherson Residence!" // If you are the only person calling, you might say this: // "This is the illustrious Kermit McFrog! Pick up the Phone, someone!!" // If you are calling from a business, you might pronounce a more sedate introduction,like, // "Fritz from McDonalds calling.", or perhaps the more original introduction: // "John, from the Park County Morgue. You stab 'em, we slab 'em!". // Just one caution: the kids will hear what you record every time // you call. So watch your language! // I will begin recording after the tone. // When you are done, hit the # key. Gather your thoughts and get // ready. Remember, the # key will end the recording, and play back // your intro. Good Luck, and Thank you!" goto 2|begin; } 2 => { begin: Background(intro-start); // OK, here we go! After the beep, please give your introduction. Background(beep); Record(priv-callerintros/${CALLERID(num)}:gsm,3); Background(priv-callerintros/${CALLERID(num)}); goto home-introduction|s|begin; } t => { goto s|begin; } i => { Background(invalid); goto s|begin; } o => { goto s|begin; } } context homeline-kids { s => { begin: Background(murphy-homeline-kids); // Which Kid? 1=Sean, 2:Eric, 3:Ryan, 4:Kyle, 5:Amber, 6:Alex, 7:Neal } 1 => { // SEAN TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/3/greet.wav&); // &std-priv-exten(Zap/3r2&Zap/5r2,3,35,mtw,telemarket,telemarket); &std-priv-exten(IAX2/seaniax&Zap/5r2,3,35,mtw,telemarket,telemarket); goto homeline|s|loopback; } 2 => { // ERIC TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/4/greet.wav&); Voicemail(u4); goto homeline|s|loopback; // SetMusicOnHold(erics); // TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); // TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/4/greet.wav&); // &std-priv-exten(Zap/3r2&Zap/5r2,4,35,mtw,telemarket,telemarket); // goto homeline|s|loopback; } 3 => { // RYAN TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/5/greet.wav&); &std-priv-exten(Zap/3r2&Zap/5r2,5,35,mtw,telemarket,telemarket); goto homeline|s|loopback; } 4 => { // KYLE TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/6/greet.wav&); &std-priv-exten(Zap/3r2&Zap/5r2,6,35,mtw,telemarket,telemarket); goto homeline|s|loopback; } 5 => { TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/7/greet.wav&); &std-priv-exten(Zap/3r2&Zap/5r2,7,35,mtw,telemarket,telemarket); goto homeline|s|loopback; } 6 => { TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/8/greet.wav&); &std-priv-exten(Zap/3r2&Zap/5r2,8,35,mtw,telemarket,telemarket); goto homeline|s|loopback; } 7 => { TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/9/greet.wav&); &std-priv-exten(Zap/3r2&Zap/5r2,9,35,mtw,telemarket,telemarket); goto homeline|s|loopback; } t => { goto s|begin; } i => { Background(invalid); goto s|begin; } o => { goto s|begin; } } context voipworkline { s => { begin: Answer(); TrySystem(/usr/local/bin/who-is-it ${CALLERID(num)} "${CALLERID(name)}"&); goto workline|s|loopback; } 7075679201 => { Answer(); TrySystem(/usr/local/bin/who-is-it ${CALLERID(num)} "${CALLERID(name)}"&); goto workline|s|loopback; } } context workline { s => { begin: Answer(); Wait(1); Set(repeatcount=0); Zapateller(nocallerid); // PrivacyManager(); // if( "${PRIVACYMGRSTATUS}" = "FAILED" ) // { // goto privacyManagerFailed|s|begin; // } &fillcidname(); TrySystem(/usr/local/bin/who-is-it ${CALLERID(num)} "${CALLERID(name)}"&); loopback: Background(greetings/greeting); //script: Hello Background(murphy-office-intro1); //script: welcome to Steve Murphy's office. If you are dialing // this number because it was on a calling list of any sort, dial 6. // Otherwise, dial 1, and hopefully, you will reach Steve. } 1 => { TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/1/greet.wav&); &std-priv-exten(Zap/6&Sip/murf,1,30,mtw,telemarket,telemarket); goto s|loopback; } 4 => { VoicemailMain(); goto s|loopback; } 6 => { goto telemarket|s|begin; } 793 => { // check the tone recognition Read(zz,,0,,1,0); SayDigits(${zz}); } t => { repeatcount=${repeatcount} + 1; if( ${repeatcount} < 3 ) { goto s|loopback; // just loopback isn't enough } Hangup(); } i => { Background(invalid); goto s|loopback; } o => { Congestion(); } fax => { Answer(); Dial(Zap/4); } } context dialFWD { ignorepat => 8; ignorepat => 9; _83. => { Set(CALLERID(name)=${FWDCIDNAME}); Dial(IAX2/${FWDNUMBER}:${FWDPASSWORD}@iax2.fwdnet.net/${EXTEN:2},60,r); Congestion(); } _82NXX => { Set(CALLERID(name)=${FWDCIDNAME}); Dial(IAX2/${FWDNUMBER}:${FWDPASSWORD}@iax2.fwdnet.net/${EXTEN:2},60,r); Congestion(); } _92NXX => { Set(CALLERID(name)=${FWDCIDNAME}); Dial(IAX2/${FWDNUMBER}:${FWDPASSWORD}@iax2.fwdnet.net/${EXTEN:2},60,r); Congestion(); } } context dialiaxtel { ignorepat => 8; ignorepat => 9; _81700NXXXXXX => { Dial(IAX2/zorch:zilchnoodle@iaxtel.com/${EXTEN:1}@iaxtel); } _81800NXXXXXX => { Dial(IAX2/zorch:zilchnoodle@iaxtel.com/${EXTEN:1}@iaxtel); } _91700NXXXXXX => { Dial(IAX2/zorch:zilchnoodle@iaxtel.com/${EXTEN:1}@iaxtel); } _91800NXXXXXX => { Dial(IAX2/zorch:zilchnoodle@iaxtel.com/${EXTEN:1}@iaxtel); } } context dialgoiax { ignorepat => 9; _93. => { Set(CALLERID(name)="Joe Worker"); Dial(IAX2/878201007658:stickyfinger295@server1.goiax.com/${EXTEN:2},60,r); Congestion(); } } context homefirst { ignorepat => 9; _91NXXNXXXXXX => { &ciddial(${EXTEN:1},${EXTEN:2},30,TW,Zap/1); } _9754XXXX => { &ciddial(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9574XXXX => { &ciddial(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9202XXXX => { &ciddial(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9219XXXX => { &ciddial(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9254XXXX => { &ciddial(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9716XXXX => { &ciddial(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9NXXXXXX => { &ciddial(1707${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9011. => { &ciddial(${EXTEN:1},${EXTEN:1},30,TW,Zap/1); } _9911 => { Dial(Zap/1/911,30,T); } _9411 => { Dial(Zap/1/411,30,T); } } context workfirst { ignorepat => 9; _91NXXNXXXXXX => { &ciddial2(${EXTEN:1},${EXTEN:2},30,TW,Zap/1); } _9754XXXX => { &ciddial2(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9574XXXX => { &ciddial2(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9202XXXX => { &ciddial2(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9219XXXX => { &ciddial2(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9254XXXX => { &ciddial2(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9716XXXX => { &ciddial2(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9NXXXXXX => { &ciddial2(1707${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9911 => { Dial(Zap/1/911,30,T); } _9411 => { Dial(Zap/1/411,30,T); } } context force_cell { ignorepat => 8; _81NXXNXXXXXX => { &ciddial(${EXTEN:1}#,${EXTEN:2},30,TW,Zap/2); } _8754XXXX => { &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); } _8574XXXX => { &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); } _8202XXXX => { &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); } _8219XXXX => { &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); } _8254XXXX => { &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); } _8716XXXX => { &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); } _8NXXXXXX => { &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); } _8911 => { Dial(Zap/1/911|30|T); } _8411 => { Dial(Zap/1/411|30|T); } } context force_home { ignorepat => 8; _81NXXNXXXXXX => { &ciddial3(${EXTEN:1}#,${EXTEN:2},30,TW,Zap/1); } _8754XXXX => { &ciddial3(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); } _8574XXXX => { &ciddial3(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); } _8202XXXX => { &ciddial3(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); } _8219XXXX => { &ciddial3(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); } _8254XXXX => { &ciddial3(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); } _8716XXXX => { &ciddial3(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); } _8NXXXXXX => { &ciddial3(1707${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); } _8911 => { Dial(Zap/1/911|30|T); } _8411 => { Dial(Zap/1/411|30|T); } } context homeext { ignorepat => 8; ignorepat => 9; includes { parkedcalls; homefirst; force_cell; } s => { loopback: Wait(0); } 1 => { &std-priv-exten(Zap/3&Zap/5,2,35,mtw,telemarket,telemarket); goto s|loopback; } 2 => { &std-priv-exten(Zap/6&Zap/5,1,35,mpA(beep3)Tt,telemarket,telemarket); goto s|loopback; } 4 => { VoicemailMain(); } 5 => { Record(recording:gsm); Background(recording); } 6 => { Background(recording); } 760 => { DateTime(); goto s|loopback; } 761 => { Record(announcement:gsm); TrySystem(/usr/bin/play /var/lib/asterisk/sounds/announcement.gsm&); goto s|loopback; } 762 => { agi(tts-riddle.agi); Background(gsm/what-time-it-is2); SayUnixTime(); goto s|loopback; } 763 => { Set(CALLERID(num)=); Dial(Zap/6r3,35,mptA(beep3)); //results: it should ALWAYS ask for an intro; the intro should not be left behind Hangup(); } 764 => { Set(CALLERID(num)=); Dial(Zap/6r3,35,mptnA(beep3)); //results: Don't save the intro; shouldn't anyway if no callerid Hangup(); } 765 => { Set(CALLERID(num)=); Dial(Zap/6r3,35,mptNA(beep3)); //results: Don't screen if there's CALLERID; it should screen the call. Hangup(); } 766 => { Dial(Zap/6r3,35,mptNA(beep3)); //results: Don't screen if there's CALLERID; it should screen the call. Hangup(); } 767 => { Dial(Zap/6r3,35,mptnA(beep3)); //results: Don't save the intro; the interesting case, because callerID should be present. Hangup(); } 769 => { Playtones(dial); Wait(2); Playtones(busy); Wait(2); Playtones(ring); Wait(2); Playtones(congestion); Wait(2); Playtones(callwaiting); Wait(2); Playtones(dialrecall); Wait(2); Playtones(record); Wait(2); Playtones(info); Wait(5); Hangup(); } 790 => { MeetMe(790,p); } 792 => { goto pageall|s|begin; } 795 => { AGI(wakeup.agi);Congestion(); } 544716 => { // Incoming call from FWD TrySystem(/usr/local/bin/who-is-it ${CALLERID(num)} "${CALLERID(name)}"&); goto s|loopback; } i => { Background(invalid); goto s|loopback; } o => { goto s|loopback; } t => { Congestion(); } } context fromvmhome { 1 => { Dial(Zap/6&Sip/murf|20|Tt); } 2 => { Dial(Zap/3&Zap/5|20|Tt); } _707202XXXX => { &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707219XXXX => { &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707254XXXX => { &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707716XXXX => { &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707754XXXX => { &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707574XXXX => { &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); } _NXXNXXXXXX => { &ciddial(1${EXTEN},${EXTEN},30,TW,Zap/1); } _1NXXNXXXXXX => { // HAND DIALING &ciddial(${EXTEN},${EXTEN:1},30,TW,Zap/1); } _754XXXX => { &ciddial(${EXTEN},707${EXTEN},30,TW,Zap/1); } _574XXXX => { &ciddial(${EXTEN},707${EXTEN},30,TW,Zap/1); } _NXXXXXX => { &ciddial(1707${EXTEN},707${EXTEN},30,TW,Zap/1); } _911 => { &ciddial(911,911,30,TW,Zap/1); } _411 => { &ciddial(411,411,30,TW,Zap/1); } } context fromvmwork { 1 => { Dial(Zap/6&Sip/murf|20|Tt); } 2 => { Dial(Zap/3&Zap/5|20|Tt); } _707202XXXX => { &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707219XXXX => { &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707254XXXX => { &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707716XXXX => { &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707754XXXX => { &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707574XXXX => { &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); } _NXXNXXXXXX => { &ciddial(1${EXTEN},${EXTEN},30,TW,Zap/1); } _1NXXNXXXXXX => { // HAND DIALING &ciddial(${EXTEN},${EXTEN:1},30,TW,Zap/1); } _754XXXX => { &ciddial(${EXTEN},707${EXTEN},30,TW,Zap/1); } _574XXXX => { &ciddial(${EXTEN},707${EXTEN},30,TW,Zap/1); } _NXXXXXX => { &ciddial(1707${EXTEN},707${EXTEN},30,TW,Zap/1); } 911 => { &ciddial(911,911,30,TW,Zap/1); } 411 => { &ciddial(411,411,30,TW,Zap/1); } } context fromSeanUniden { includes { parkedcalls; } 21 => { Dial(IAX2/seaniax,20,T); } _707202XXXX => { &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707219XXXX => { &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707254XXXX => { &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707716XXXX => { &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707754XXXX => { &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707574XXXX => { &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); } _NXXNXXXXXX => { &ciddial(1${EXTEN},${EXTEN},30,TW,Zap/1); } _1NXXNXXXXXX => { &ciddial(${EXTEN},${EXTEN:1},30,TW,Zap/1); } _754XXXX => { &ciddial(${EXTEN},707${EXTEN},30,TW,Zap/1); } _574XXXX => { &ciddial(${EXTEN},707${EXTEN},30,TW,Zap/1); } _NXXXXXX => { &ciddial(1707${EXTEN},707${EXTEN},30,TW,Zap/1); } 911 => { &ciddial(911,911,30,TW,Zap/1); } 411 => { &ciddial(411,411,30,TW,Zap/1); } } context workext { ignorepat => 8; ignorepat => 9; includes { parkedcalls; workfirst; force_home; dialFWD; dialiaxtel; dialgoiax; } s => { loopback: Wait(0); } 1 => { Dial(Zap/3&Zap/5,20,tT); } 2 => { Dial(Zap/5&Zap/6,20,tT); } 21 => { Dial(IAX2/seaniax,20,T); } 22 => { Set(CALLERID(num)=1234567890); Set(CALLERID(name)=TestCaller); Dial(Zap/5,20,mP()A(beep)tw); NoOp(here is dialstatus: ${DIALSTATUS}...); goto s|loopback; } 4 => { VoicemailMain(); goto s|loopback; } 5 => { Record(recording:gsm); Background(recording); } 6 => { ZapBarge(); } 760 => { DateTime(); goto s|loopback; } 761 => { ZapBarge(); goto s|loopback; } 765 => { Playback(demo-echotest); Echo(); Playback(demo-echodone); goto s|loopback; } 766 => { Festival(The other thing to watch is neuro-electronics: the ability to interface technology with our neural system: My wife: Sigrid: has had a cochlear implant since 1996. This once profoundly deaf person now uses the phone: recognizes accents: and listens to movies and recorded books.); goto s|loopback; } 767 => { agi(tts-riddle.agi); Background(gsm/what-time-it-is2); SayUnixTime(); goto s|loopback; } 768 => { agi(tts-computer.agi); } 771 => { eagi(eagi-test); agi(my-agi-test); } 772 => { agi(wakeup.agi); } 775 => { if( ${EXTEN}=${EXTEN} ) { BackGround(digits/1); } else { BackGround(digits/0); } if( ${EXTEN}=${LANGUAGE} ) { BackGround(digits/1); } else { BackGround(digits/0); } BackGround(digits/2); } 776 => { Set(TEST=00359889811777); if( ${TEST}= 00359889811777 ) { BackGround(digits/1); } else { BackGround(digits/0); } if( ${TEST}= 00359889811888 ) { BackGround(digits/1); } else { BackGround(digits/0); } Hangup(); } 790 => { MeetMe(790,p); } 792 => { goto pageall|s|begin; } 793 => { #include "include1.ael2" } 795 => { AGI(wakeup.agi); Congestion(); } 797 => { Set(CONFCIDNA=${CALLERID(name)}); Set(CONFCIDNU=${CALLERID(num)}); AGI(callall); AGI(submit-announce.agi); Hangup(); } } context wakeup { 3 => { Dial(Zap/3|30); } 4 => { Dial(Zap/4|30); } 5 => { Dial(Zap/5|30); } 6 => { Dial(Zap/6|30); } 99 => { Dial(IAX2/murfiaxphone|30); } 97 => { Dial(IAX2/ryaniax|30); } 94 => { Dial(IAX2/seaniax|30); } } context announce-all { s => { begin: MeetMe(5555,dtqp); MeetMeAdmin(5555,K); Hangup(); } h => { MeetMeAdmin(5555,K); Hangup(); } } // now include the telemarketer torture scripts! #include "telemarket_torture.ael2" asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-ntest100000644000175000017500000006544311046713743020571 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -n option if you aren't interested in seeing all the instructions generated by the compiler) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:115 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:pbx_ael.c line:128 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1-4: The macro endsess does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 6-9: The macro nullchk does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 11-26: The macro endcall does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:2297 func: check_switch_expr Warning: file ./extensions.ael, line 13-13: A default case was automatically added to the switch. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 28-44: The macro endcall2 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:2297 func: check_switch_expr Warning: file ./extensions.ael, line 36-36: A default case was automatically added to the switch. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 46-68: The macro endcall3 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:2297 func: check_switch_expr Warning: file ./extensions.ael, line 48-48: A default case was automatically added to the switch. LOG: lev:3 file:pval.c line:2297 func: check_switch_expr Warning: file ./extensions.ael, line 60-60: A default case was automatically added to the switch. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 70-96: The macro endcall4 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:2297 func: check_switch_expr Warning: file ./extensions.ael, line 72-72: A default case was automatically added to the switch. LOG: lev:3 file:pval.c line:2297 func: check_switch_expr Warning: file ./extensions.ael, line 84-84: A default case was automatically added to the switch. LOG: lev:3 file:pval.c line:2297 func: check_switch_expr Warning: file ./extensions.ael, line 87-87: A default case was automatically added to the switch. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 98-131: The macro endcall5 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:2297 func: check_switch_expr Warning: file ./extensions.ael, line 106-106: A default case was automatically added to the switch. LOG: lev:3 file:pval.c line:2297 func: check_switch_expr Warning: file ./extensions.ael, line 119-119: A default case was automatically added to the switch. LOG: lev:3 file:pval.c line:2297 func: check_switch_expr Warning: file ./extensions.ael, line 122-122: A default case was automatically added to the switch. LOG: lev:2 file:pbx_ael.c line:131 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. Executed ast_context_find_or_create(conts, name=endsess, registrar=pbx_ael); Executed ast_context_find_or_create(conts, name=nullchk, registrar=pbx_ael); Executed ast_context_find_or_create(conts, name=endcall, registrar=pbx_ael); Executed ast_context_find_or_create(conts, name=endcall2, registrar=pbx_ael); Executed ast_context_find_or_create(conts, name=endcall3, registrar=pbx_ael); Executed ast_context_find_or_create(conts, name=endcall4, registrar=pbx_ael); Executed ast_context_find_or_create(conts, name=endcall5, registrar=pbx_ael); Executed ast_add_extension2(context=endsess, rep=0, exten=s, priority=1, label=(null), callerid=(null), appl=NoOp, data=hithere, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endsess, rep=0, exten=s, priority=2, label=(null), callerid=(null), appl=Return, data=, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=nullchk, rep=0, exten=s, priority=1, label=(null), callerid=(null), appl=Set, data=LOCAL(type)=${ARG1}, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=nullchk, rep=0, exten=s, priority=2, label=(null), callerid=(null), appl=NoOp, data=${type} is this, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=nullchk, rep=0, exten=s, priority=3, label=(null), callerid=(null), appl=Return, data=, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall, rep=0, exten=s, priority=1, label=(null), callerid=(null), appl=Set, data=LOCAL(type)=${ARG1}, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall, rep=0, exten=s, priority=2, label=(null), callerid=(null), appl=Set, data=~~EXTEN~~=${EXTEN}, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall, rep=0, exten=s, priority=3, label=(null), callerid=(null), appl=Goto, data=sw-1-${type},10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall, rep=0, exten=s, priority=4, label=(null), callerid=(null), appl=NoOp, data=Finish switch-endcall-1, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall, rep=0, exten=s, priority=5, label=(null), callerid=(null), appl=Return, data=, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall, rep=0, exten=_sw-1-., priority=10, label=(null), callerid=(null), appl=Goto, data=s,4, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall, rep=0, exten=sw-1-, priority=10, label=(null), callerid=(null), appl=Goto, data=sw-1-.|10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall, rep=0, exten=sw-1-out, priority=10, label=(null), callerid=(null), appl=Gosub, data=nullchk,s,1(callid), FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall, rep=0, exten=sw-1-out, priority=11, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?12:15, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall, rep=0, exten=sw-1-out, priority=12, label=(null), callerid=(null), appl=Gosub, data=endsess,s,1, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall, rep=0, exten=sw-1-out, priority=13, label=(null), callerid=(null), appl=Goto, data=sw-1-out,ptr1, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall, rep=0, exten=sw-1-out, priority=14, label=(null), callerid=(null), appl=Goto, data=17, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall, rep=0, exten=sw-1-out, priority=15, label=ptr1, callerid=(null), appl=Softhangup, data=${CHANNEL}, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall, rep=0, exten=sw-1-out, priority=16, label=(null), callerid=(null), appl=Goto, data=s,4, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall, rep=0, exten=sw-1-out, priority=17, label=(null), callerid=(null), appl=NoOp, data=Finish if-sw-endcall-out-1-2, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall, rep=0, exten=sw-1-out, priority=18, label=(null), callerid=(null), appl=Noop, data=esac, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall, rep=0, exten=sw-1-out, priority=19, label=(null), callerid=(null), appl=Goto, data=sw-1-.,10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall2, rep=0, exten=s, priority=1, label=(null), callerid=(null), appl=Set, data=LOCAL(type)=${ARG1}, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall2, rep=0, exten=s, priority=2, label=(null), callerid=(null), appl=Set, data=~~EXTEN~~=${EXTEN}, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall2, rep=0, exten=s, priority=3, label=(null), callerid=(null), appl=Goto, data=sw-3-${type},10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall2, rep=0, exten=s, priority=4, label=(null), callerid=(null), appl=NoOp, data=Finish switch-endcall2-3, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall2, rep=0, exten=s, priority=5, label=(null), callerid=(null), appl=Return, data=, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall2, rep=0, exten=_sw-3-., priority=10, label=(null), callerid=(null), appl=Goto, data=s,4, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall2, rep=0, exten=sw-3-, priority=10, label=(null), callerid=(null), appl=Goto, data=sw-3-.|10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall2, rep=0, exten=sw-3-out2, priority=10, label=ptr1, callerid=(null), appl=Softhangup, data=${CHANNEL}, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall2, rep=0, exten=sw-3-out2, priority=11, label=(null), callerid=(null), appl=Goto, data=s,4, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall2, rep=0, exten=sw-3-out2, priority=12, label=(null), callerid=(null), appl=Noop, data=esac, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall2, rep=0, exten=sw-3-out2, priority=13, label=(null), callerid=(null), appl=Goto, data=sw-3-.,10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall2, rep=0, exten=sw-3-out, priority=10, label=(null), callerid=(null), appl=Gosub, data=nullchk,s,1(callid), FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall2, rep=0, exten=sw-3-out, priority=11, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?12:14, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall2, rep=0, exten=sw-3-out, priority=12, label=(null), callerid=(null), appl=Gosub, data=endsess,s,1, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall2, rep=0, exten=sw-3-out, priority=13, label=(null), callerid=(null), appl=Goto, data=sw-3-out2,ptr1, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall2, rep=0, exten=sw-3-out, priority=14, label=(null), callerid=(null), appl=NoOp, data=Finish if-sw-endcall2-out-3-4, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall2, rep=0, exten=sw-3-out, priority=15, label=(null), callerid=(null), appl=Goto, data=sw-3-out2,10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=s, priority=1, label=(null), callerid=(null), appl=Set, data=LOCAL(type)=${ARG1}, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=s, priority=2, label=(null), callerid=(null), appl=Set, data=~~EXTEN~~=${EXTEN}, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=s, priority=3, label=(null), callerid=(null), appl=Goto, data=sw-5-${type},10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=s, priority=4, label=(null), callerid=(null), appl=NoOp, data=Finish switch-endcall3-5, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=s, priority=5, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?6:7, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=s, priority=6, label=(null), callerid=(null), appl=Goto, data=sw-8-out,ptr1, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=s, priority=7, label=(null), callerid=(null), appl=NoOp, data=Finish if-endcall3-7, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=s, priority=8, label=(null), callerid=(null), appl=Goto, data=sw-8-${type},10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=s, priority=9, label=(null), callerid=(null), appl=NoOp, data=Finish switch-endcall3-8, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=s, priority=10, label=(null), callerid=(null), appl=Return, data=, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=_sw-8-., priority=10, label=(null), callerid=(null), appl=Goto, data=s,9, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=sw-8-, priority=10, label=(null), callerid=(null), appl=Goto, data=sw-8-.|10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=sw-8-out, priority=10, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?11:13, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=sw-8-out, priority=11, label=ptr1, callerid=(null), appl=Softhangup, data=${CHANNEL}, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=sw-8-out, priority=12, label=(null), callerid=(null), appl=Goto, data=s,9, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=sw-8-out, priority=13, label=(null), callerid=(null), appl=NoOp, data=Finish if-sw-endcall3-out-8-9, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=sw-8-out, priority=14, label=(null), callerid=(null), appl=Noop, data=esac, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=sw-8-out, priority=15, label=(null), callerid=(null), appl=Goto, data=sw-8-.,10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=_sw-5-., priority=10, label=(null), callerid=(null), appl=Goto, data=s,4, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=sw-5-, priority=10, label=(null), callerid=(null), appl=Goto, data=sw-5-.|10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=sw-5-out, priority=10, label=(null), callerid=(null), appl=Gosub, data=nullchk,s,1(callid), FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=sw-5-out, priority=11, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?12:14, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=sw-5-out, priority=12, label=(null), callerid=(null), appl=Gosub, data=endsess,s,1, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=sw-5-out, priority=13, label=(null), callerid=(null), appl=Goto, data=sw-8-out,ptr1, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=sw-5-out, priority=14, label=(null), callerid=(null), appl=NoOp, data=Finish if-sw-endcall3-out-5-6, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=sw-5-out, priority=15, label=(null), callerid=(null), appl=Noop, data=esac, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall3, rep=0, exten=sw-5-out, priority=16, label=(null), callerid=(null), appl=Goto, data=sw-5-.,10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=s, priority=1, label=(null), callerid=(null), appl=Set, data=LOCAL(type)=${ARG1}, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=s, priority=2, label=(null), callerid=(null), appl=Set, data=~~EXTEN~~=${EXTEN}, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=s, priority=3, label=(null), callerid=(null), appl=Goto, data=sw-10-${type},10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=s, priority=4, label=(null), callerid=(null), appl=NoOp, data=Finish switch-endcall4-10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=s, priority=5, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?6:7, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=s, priority=6, label=(null), callerid=(null), appl=Goto, data=sw-14-in,ptr1, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=s, priority=7, label=(null), callerid=(null), appl=NoOp, data=Finish if-endcall4-12, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=s, priority=8, label=(null), callerid=(null), appl=Goto, data=sw-13-${type},10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=s, priority=9, label=(null), callerid=(null), appl=NoOp, data=Finish switch-endcall4-13, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=s, priority=10, label=(null), callerid=(null), appl=Return, data=, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=_sw-13-., priority=10, label=(null), callerid=(null), appl=Goto, data=s,9, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=sw-13-, priority=10, label=(null), callerid=(null), appl=Goto, data=sw-13-.|10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=sw-13-out, priority=10, label=(null), callerid=(null), appl=Goto, data=sw-14-${type},10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=sw-13-out, priority=11, label=(null), callerid=(null), appl=NoOp, data=Finish switch-sw-endcall4-out-13-14, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=sw-13-out, priority=12, label=(null), callerid=(null), appl=Goto, data=sw-13-.,10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=_sw-14-., priority=10, label=(null), callerid=(null), appl=Goto, data=sw-13-out,11, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=sw-14-, priority=10, label=(null), callerid=(null), appl=Goto, data=sw-14-.|10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=sw-14-in, priority=10, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?11:13, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=sw-14-in, priority=11, label=ptr1, callerid=(null), appl=Softhangup, data=${CHANNEL}, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=sw-14-in, priority=12, label=(null), callerid=(null), appl=Goto, data=sw-13-out,11, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=sw-14-in, priority=13, label=(null), callerid=(null), appl=NoOp, data=Finish if-sw-sw-endcall4-out-13-in-14-15, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=sw-14-in, priority=14, label=(null), callerid=(null), appl=Noop, data=esac, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=sw-14-in, priority=15, label=(null), callerid=(null), appl=Goto, data=sw-14-.,10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=_sw-10-., priority=10, label=(null), callerid=(null), appl=Goto, data=s,4, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=sw-10-, priority=10, label=(null), callerid=(null), appl=Goto, data=sw-10-.|10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=sw-10-out, priority=10, label=(null), callerid=(null), appl=Gosub, data=nullchk,s,1(callid), FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=sw-10-out, priority=11, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?12:14, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=sw-10-out, priority=12, label=(null), callerid=(null), appl=Gosub, data=endsess,s,1, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=sw-10-out, priority=13, label=(null), callerid=(null), appl=Goto, data=sw-14-in,ptr1, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=sw-10-out, priority=14, label=(null), callerid=(null), appl=NoOp, data=Finish if-sw-endcall4-out-10-11, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=sw-10-out, priority=15, label=(null), callerid=(null), appl=Noop, data=esac, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall4, rep=0, exten=sw-10-out, priority=16, label=(null), callerid=(null), appl=Goto, data=sw-10-.,10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=s, priority=1, label=(null), callerid=(null), appl=Set, data=LOCAL(type)=${ARG1}, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=s, priority=2, label=(null), callerid=(null), appl=Set, data=~~EXTEN~~=${EXTEN}, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=s, priority=3, label=(null), callerid=(null), appl=Goto, data=sw-16-${type},10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=s, priority=4, label=(null), callerid=(null), appl=NoOp, data=Finish switch-endcall5-16, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=s, priority=5, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?6:7, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=s, priority=6, label=(null), callerid=(null), appl=Goto, data=sw-21-in,ptr1, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=s, priority=7, label=(null), callerid=(null), appl=NoOp, data=Finish if-endcall5-19, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=s, priority=8, label=(null), callerid=(null), appl=Goto, data=sw-20-${type},10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=s, priority=9, label=(null), callerid=(null), appl=NoOp, data=Finish switch-endcall5-20, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=s, priority=10, label=(null), callerid=(null), appl=Return, data=, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=_sw-20-., priority=10, label=(null), callerid=(null), appl=Goto, data=s,9, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-20-, priority=10, label=(null), callerid=(null), appl=Goto, data=sw-20-.|10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-20-out, priority=10, label=(null), callerid=(null), appl=Goto, data=sw-21-${type},10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-20-out, priority=11, label=(null), callerid=(null), appl=NoOp, data=Finish switch-sw-endcall5-out-20-21, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-20-out, priority=12, label=(null), callerid=(null), appl=Goto, data=sw-20-.,10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=_sw-21-., priority=10, label=(null), callerid=(null), appl=Goto, data=sw-20-out,11, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-21-, priority=10, label=(null), callerid=(null), appl=Goto, data=sw-21-.|10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-21-in, priority=10, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?11:13, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-21-in, priority=11, label=ptr1, callerid=(null), appl=Softhangup, data=${CHANNEL}, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-21-in, priority=12, label=(null), callerid=(null), appl=Goto, data=sw-20-out,11, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-21-in, priority=13, label=(null), callerid=(null), appl=NoOp, data=Finish if-sw-sw-endcall5-out-20-in-21-22, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-21-in, priority=14, label=(null), callerid=(null), appl=Noop, data=esac, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-21-in, priority=15, label=(null), callerid=(null), appl=Goto, data=sw-21-.,10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=_sw-16-., priority=10, label=(null), callerid=(null), appl=Goto, data=s,4, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-16-, priority=10, label=(null), callerid=(null), appl=Goto, data=sw-16-.|10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-16-in, priority=10, label=(null), callerid=(null), appl=Gosub, data=nullchk,s,1(callid), FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-16-in, priority=11, label=ptr2, callerid=(null), appl=GotoIf, data=$[${testnotnull}]?12:14, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-16-in, priority=12, label=(null), callerid=(null), appl=Gosub, data=endsess,s,1, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-16-in, priority=13, label=(null), callerid=(null), appl=Goto, data=sw-21-in,ptr1, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-16-in, priority=14, label=(null), callerid=(null), appl=NoOp, data=Finish if-sw-endcall5-in-16-18, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-16-in, priority=15, label=(null), callerid=(null), appl=Noop, data=esac, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-16-in, priority=16, label=(null), callerid=(null), appl=Goto, data=sw-16-.,10, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-16-out, priority=10, label=(null), callerid=(null), appl=Gosub, data=nullchk,s,1(callid), FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-16-out, priority=11, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?12:14, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-16-out, priority=12, label=(null), callerid=(null), appl=Gosub, data=endsess,s,1, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-16-out, priority=13, label=(null), callerid=(null), appl=Goto, data=sw-21-in,ptr1, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-16-out, priority=14, label=(null), callerid=(null), appl=NoOp, data=Finish if-sw-endcall5-out-16-17, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=endcall5, rep=0, exten=sw-16-out, priority=15, label=(null), callerid=(null), appl=Goto, data=sw-16-in,10, FREE, registrar=pbx_ael); LOG: lev:2 file:pbx_ael.c line:134 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. Executed ast_merge_contexts_and_delete(); LOG: lev:2 file:pbx_ael.c line:139 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. Executed ast_walk_contexts(); LOG: lev:2 file:pbx_ael.c line:142 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. LOG: lev:4 file:ael2_parse line:518 func: main 7 contexts, 37 extensions, 136 priorities asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-test110000644000175000017500000000265010723063404020374 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:113 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:pbx_ael.c line:126 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:4 file:pval.c line:1147 func: check_label Error: file ./extensions.ael, line 13-13: Duplicate label lab1! Previously defined at file ./extensions.ael, line 8. LOG: lev:3 file:pval.c line:2284 func: check_switch_expr Warning: file ./extensions.ael, line 32-32: A default case was automatically added to the switch. LOG: lev:3 file:pval.c line:2284 func: check_switch_expr Warning: file ./extensions.ael, line 44-44: A default case was automatically added to the switch. LOG: lev:3 file:pval.c line:2284 func: check_switch_expr Warning: file ./extensions.ael, line 47-47: A default case was automatically added to the switch. LOG: lev:4 file:pval.c line:1147 func: check_label Error: file ./extensions.ael, line 49-49: Duplicate label ptr1! Previously defined at file ./extensions.ael, line 33. LOG: lev:4 file:pbx_ael.c line:139 func: pbx_load_module Sorry, but 0 syntax errors and 2 semantic errors were detected. It doesn't make sense to compile. LOG: lev:4 file:ael2_parse line:531 func: main 0 contexts, 0 extensions, 0 priorities asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-test160000644000175000017500000000202410723063404020374 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:113 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:pbx_ael.c line:126 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:129 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. LOG: lev:3 file:pval.c line:3786 func: add_extensions This file is Empty! LOG: lev:2 file:pbx_ael.c line:131 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:134 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:137 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. LOG: lev:4 file:ael2_parse line:531 func: main 1 contexts, 0 extensions, 0 priorities asterisk-1.6.1.0/pbx/ael/ael-test/ael-test1/0000755000175000017500000000000011175405520017613 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-test1/extensions.ael0000644000175000017500000000626410467425741022517 0ustar maniacmaniac macro testdial(number, timeout) { Dial(IAX2/vpconnect-t02/${number},${timeout},${OG_DIAL_FLAGS}); switch (${DIALSTATUS}) { case CHANUNAVAIL: goto dial-trunk2; break; default: NoOp(t02 Unavailable - ${DIALSTATUS}); return; } dial-trunk2: Dial(IAX2/vpconnect-t01/${number},${timeout},${OG_DIAL_FLAGS}); } macro exten-gen(name,pword) { if( ${DB_EXISTS(org/${GroupID}/${name}/secret)} = 0 ) goto other|nomatch|begin; if( ${DB(org/${GroupID}/${name}/secret)}foo != ${pword}foo ) goto other|nomatch|begin; }; context what { who => { random(51) NoOp(This should appear 51% of the time); random( 60 ) { NoOp( This should appear 60% of the time ); } else { random(75) { NoOp( This should appear 30% of the time! ); } else { NoOp( This should appear 10% of the time! ); } } } } context other { nomatch => { begin: NoOp(Hello!); switch(${DIALSTATUS}) { case BUSY: NoOp(wow); case TORTURE: NoOp(woow); }; NoOp(woohoo); }; }; context testloop { includes { other|16:00-23:59|m0n-fri|*|*; }; 1 => { for (x=0; ${x} < 3; x=${x} + 1) { Verbose(x is ${x} !); if( ${x} = 1 ) continue; if( ${x} = 2 ) break; }; ifTime(14:00-25:00|sat-sun|*|*) { BackGround(Hello); } else BackGround(Sorry); NoOp(This is a totally useless NOOP); }; 2 => { y=10; while (${y} >= 0) { Verbose(y is ${y} !); if( ${y} = 1 ) continue; if( ${y} = 2 ) break; if( ${y} = 3 ) return; y=${y}-1; }; }; regexten hint(nasty/Thingy&nasty/Thingamabob) 3 => { for (x=0; ${x} < 3; x=${x} + 1) { Verbose(x is ${x} !); if( ${x} = 4 ) break; if( ${x} = 5 ) continue; if( ${x} = 6 ) return; y=10; while (${y} >= 0) { Verbose(y is ${y} !); if( ${y} = 4 ) break; if( ${y} = 5 ) continue; if( ${y} = 6 ) return; y=${y}-1; }; }; }; 4 => { y=10; while (${y} >= 0) { Verbose(y is ${y} !); if( ${y} = 4 ) break; if( ${y} = 5 ) continue; if( ${y} = 6 ) return; for (x=0; ${x} < 3; x=${x} + 1) { Verbose(x is ${x} !); if( ${x} = 4 ) break; if( ${x} = 5 ) continue; if( ${x} = 6 ) return; for (z=0; ${z} < 17; z=${z} + 1) { Verbose(z is ${z} !); Verbose(z is ${z} !); if( ${z} = 4 ) break; if( ${z} = 5 ) continue; if( ${z} = 6 ) return; Verbose(z is ${z} !); Verbose(z is ${z} !); }; }; y=${y}-1; }; }; 5 => { &exten-gen(axel,brain); }; }; asterisk-1.6.1.0/pbx/ael/ael-test/ael-vtest25/0000755000175000017500000000000011175405520020067 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-vtest25/extensions.ael0000644000175000017500000000034611060072241022745 0ustar maniacmaniaccontext test11 { 841 => { &test234("testing", ${CUT(EXTEN,,3)}); jump ${DB(uri/${uri_string})}; Set(line=${DB(uri/${uri_string})}); jump ${line}; } } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest22/0000755000175000017500000000000011175405517020062 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest22/t3/0000755000175000017500000000000011175405520020402 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest22/t3/j.ael0000644000175000017500000000005310677552172021330 0ustar maniacmaniac context j { 567 => NoOp(hi there, j); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest22/t3/i.ael0000644000175000017500000000005110677552172021325 0ustar maniacmaniaccontext i { 134 => NoOp(hi there, i); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest22/t3/g.ael0000644000175000017500000000005110677552172021323 0ustar maniacmaniaccontext g { 134 => NoOp(hi there, g); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest22/t3/h.ael0000644000175000017500000000005210677552172021325 0ustar maniacmaniac context h { 456 => NoOp(hithere, h); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest22/t2/0000755000175000017500000000000011175405517020407 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest22/t2/d.ael0000644000175000017500000000005110677552172021317 0ustar maniacmaniaccontext d { 134 => NoOp(hi there, d); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest22/t2/e.ael0000644000175000017500000000005210677552172021321 0ustar maniacmaniac context e { 456 => NoOp(hithere, e); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest22/t2/f.ael0000644000175000017500000000012210677552172021320 0ustar maniacmaniac#include "qq.ael" context f { 567 => NoOp(hi there, f); } #include "t3/*.ael" asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest22/t1/0000755000175000017500000000000011175405517020406 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest22/t1/a.ael0000644000175000017500000000005110677552172021313 0ustar maniacmaniaccontext a { 134 => NoOp(hi there, a); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest22/t1/b.ael0000644000175000017500000000005210677552172021315 0ustar maniacmaniac context b { 456 => NoOp(hithere, b); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest22/t1/c.ael0000644000175000017500000000015210677552172021317 0ustar maniacmaniac context c { 567 => NoOp(hi there, c); } #include "t2/*.ael" context w { 890 => NoOp(hi there, w); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest22/qq.ael0000644000175000017500000000005510677552172021174 0ustar maniacmaniac context qq { 567 => NoOp(hi there, qq); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest22/extensions.ael0000644000175000017500000000013210677552172022746 0ustar maniacmaniac#include "t1/*.ael" context z { 123 => NoOp(hi there, z); 124 => NoOp(hi there, z); } asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-ntest120000644000175000017500000000611010723063404020546 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -n option if you aren't interested in seeing all the instructions generated by the compiler) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:113 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:pbx_ael.c line:126 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:129 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. Executed ast_context_find_or_create(conts, name=test1, registrar=pbx_ael); Executed ast_add_extension2(context=test1, rep=0, exten=771, priority=1, label=(null), callerid=(null), appl=Set, data=i=$[0], FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test1, rep=0, exten=771, priority=2, label=(null), callerid=(null), appl=GotoIf, data=$[ ${i} <= 3]?3:6, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test1, rep=0, exten=771, priority=3, label=(null), callerid=(null), appl=NoOp, data=i is '${i}', FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test1, rep=0, exten=771, priority=4, label=(null), callerid=(null), appl=Set, data=i=$[ ${i} + 1 ], FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test1, rep=0, exten=771, priority=5, label=(null), callerid=(null), appl=Goto, data=2, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test1, rep=0, exten=771, priority=6, label=(null), callerid=(null), appl=NoOp, data=Finish for-test1-1, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test1, rep=0, exten=772, priority=1, label=(null), callerid=(null), appl=Set, data=i=$[0], FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test1, rep=0, exten=772, priority=2, label=(null), callerid=(null), appl=GotoIf, data=$[ ${i} <= 3]?3:6, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test1, rep=0, exten=772, priority=3, label=(null), callerid=(null), appl=NoOp, data=i is '${i}', FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test1, rep=0, exten=772, priority=4, label=(null), callerid=(null), appl=Set, data=i=$[ ${i} + 1 ], FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test1, rep=0, exten=772, priority=5, label=(null), callerid=(null), appl=Goto, data=2, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=test1, rep=0, exten=772, priority=6, label=(null), callerid=(null), appl=NoOp, data=Finish for-test1-2, FREE, registrar=pbx_ael); LOG: lev:2 file:pbx_ael.c line:131 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. Executed ast_merge_contexts_and_delete(); LOG: lev:2 file:pbx_ael.c line:134 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. Executed ast_walk_contexts(); LOG: lev:2 file:pbx_ael.c line:137 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. LOG: lev:4 file:ael2_parse line:531 func: main 1 contexts, 2 extensions, 12 priorities asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-ntest220000644000175000017500000001246010723063404020554 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -n option if you aren't interested in seeing all the instructions generated by the compiler) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:113 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:ael.flex line:662 func: setup_filestack --Read in included file ././t1/a.ael, 41 chars LOG: lev:2 file:ael.flex line:662 func: setup_filestack --Read in included file ././t1/b.ael, 42 chars LOG: lev:2 file:ael.flex line:662 func: setup_filestack --Read in included file ././t1/c.ael, 106 chars LOG: lev:2 file:ael.flex line:662 func: setup_filestack --Read in included file ././t2/d.ael, 41 chars LOG: lev:2 file:ael.flex line:662 func: setup_filestack --Read in included file ././t2/e.ael, 42 chars LOG: lev:2 file:ael.flex line:662 func: setup_filestack --Read in included file ././t2/f.ael, 82 chars LOG: lev:2 file:ael.flex line:662 func: setup_filestack --Read in included file ././qq.ael, 45 chars LOG: lev:2 file:ael.flex line:662 func: setup_filestack --Read in included file ././t3/g.ael, 41 chars LOG: lev:2 file:ael.flex line:662 func: setup_filestack --Read in included file ././t3/h.ael, 42 chars LOG: lev:2 file:ael.flex line:662 func: setup_filestack --Read in included file ././t3/i.ael, 41 chars LOG: lev:2 file:ael.flex line:662 func: setup_filestack --Read in included file ././t3/j.ael, 43 chars LOG: lev:2 file:pbx_ael.c line:126 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:129 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. Executed ast_context_find_or_create(conts, name=a, registrar=pbx_ael); Executed ast_context_find_or_create(conts, name=b, registrar=pbx_ael); Executed ast_context_find_or_create(conts, name=c, registrar=pbx_ael); Executed ast_context_find_or_create(conts, name=d, registrar=pbx_ael); Executed ast_context_find_or_create(conts, name=e, registrar=pbx_ael); Executed ast_context_find_or_create(conts, name=qq, registrar=pbx_ael); Executed ast_context_find_or_create(conts, name=f, registrar=pbx_ael); Executed ast_context_find_or_create(conts, name=g, registrar=pbx_ael); Executed ast_context_find_or_create(conts, name=h, registrar=pbx_ael); Executed ast_context_find_or_create(conts, name=i, registrar=pbx_ael); Executed ast_context_find_or_create(conts, name=j, registrar=pbx_ael); Executed ast_context_find_or_create(conts, name=w, registrar=pbx_ael); Executed ast_context_find_or_create(conts, name=z, registrar=pbx_ael); Executed ast_add_extension2(context=a, rep=0, exten=134, priority=1, label=(null), callerid=(null), appl=NoOp, data=hi there, a, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=b, rep=0, exten=456, priority=1, label=(null), callerid=(null), appl=NoOp, data=hithere, b, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=c, rep=0, exten=567, priority=1, label=(null), callerid=(null), appl=NoOp, data=hi there, c, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=d, rep=0, exten=134, priority=1, label=(null), callerid=(null), appl=NoOp, data=hi there, d, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=e, rep=0, exten=456, priority=1, label=(null), callerid=(null), appl=NoOp, data=hithere, e, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=qq, rep=0, exten=567, priority=1, label=(null), callerid=(null), appl=NoOp, data=hi there, qq, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=f, rep=0, exten=567, priority=1, label=(null), callerid=(null), appl=NoOp, data=hi there, f, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=g, rep=0, exten=134, priority=1, label=(null), callerid=(null), appl=NoOp, data=hi there, g, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=h, rep=0, exten=456, priority=1, label=(null), callerid=(null), appl=NoOp, data=hithere, h, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=i, rep=0, exten=134, priority=1, label=(null), callerid=(null), appl=NoOp, data=hi there, i, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=j, rep=0, exten=567, priority=1, label=(null), callerid=(null), appl=NoOp, data=hi there, j, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=w, rep=0, exten=890, priority=1, label=(null), callerid=(null), appl=NoOp, data=hi there, w, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=z, rep=0, exten=123, priority=1, label=(null), callerid=(null), appl=NoOp, data=hi there, z, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=z, rep=0, exten=124, priority=1, label=(null), callerid=(null), appl=NoOp, data=hi there, z, FREE, registrar=pbx_ael); LOG: lev:2 file:pbx_ael.c line:131 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. Executed ast_merge_contexts_and_delete(); LOG: lev:2 file:pbx_ael.c line:134 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. Executed ast_walk_contexts(); LOG: lev:2 file:pbx_ael.c line:137 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. LOG: lev:4 file:ael2_parse line:531 func: main 13 contexts, 13 extensions, 14 priorities asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-vtest130000644000175000017500000033734211122111676020574 0ustar maniacmaniac[globals] static=yes writeprotect=yes CONSOLE=Console/dsp IAXINFO=murf:tlhfckoct FWDNUMBER=544788 FWDCIDNAME="Joe-Worker" FWDPASSWORD=zingledoodle FWDRINGS=Zap/6 FWDVMBOX=1 [std-exten] exten => s,1,Set(LOCAL(ext)=${ARG1}) exten => s,2,Set(LOCAL(dev)=${ARG2}) exten => s,3,Set(~~EXTEN~~=${EXTEN}) exten => s,4,Dial(${dev}/${ext},20) exten => s,5,Goto(sw-1-${DIALSTATUS},10) exten => s,6,NoOp(Finish switch-std-exten-1) exten => s,7,Return() exten => a,1,VoiceMailMain(${ext}) exten => _sw-1-.,10,Voicemail(u${ext}) exten => _sw-1-.,11,Goto(s,6) exten => sw-1-,10,Goto(sw-1-.,10) exten => sw-1-ANSWER,10,Goto(s,6) exten => sw-1-NOANSWER,10,Voicemail(u${ext}) exten => sw-1-NOANSWER,11,Goto(s,6) exten => sw-1-BUSY,10,Voicemail(b${ext}) exten => sw-1-BUSY,11,Goto(s,6) [std-priv-exten_1] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-3-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_1-3) exten => s,12,Return() exten => _sw-3-.,10,Voicemail(u${ext}) exten => _sw-3-.,11,Goto(s,11) exten => sw-3-,10,Goto(sw-3-.,10) exten => sw-3-NOANSWER,10,Voicemail(u${ext}) exten => sw-3-NOANSWER,11,Goto(s,11) exten => sw-3-ANSWER,10,Goto(s,11) exten => sw-3-BUSY,10,Voicemail(b${ext}) exten => sw-3-BUSY,11,Goto(s,11) exten => sw-3-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-3-DONTCALL,11,Goto(s,11) exten => sw-3-TORTURE,10,Goto(${torcont},s,begin) exten => sw-3-TORTURE,11,Goto(s,11) [std-priv-exten_2] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-4-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_2-4) exten => s,12,Return() exten => _sw-4-.,10,Voicemail(u${ext}) exten => _sw-4-.,11,Goto(s,11) exten => sw-4-,10,Goto(sw-4-.,10) exten => sw-4-NOANSWER,10,Voicemail(u${ext}) exten => sw-4-NOANSWER,11,Goto(s,11) exten => sw-4-ANSWER,10,Goto(s,11) exten => sw-4-BUSY,10,Voicemail(b${ext}) exten => sw-4-BUSY,11,Goto(s,11) exten => sw-4-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-4-DONTCALL,11,Goto(s,11) exten => sw-4-TORTURE,10,Goto(${torcont},s,begin) exten => sw-4-TORTURE,11,Goto(s,11) [std-priv-exten_3] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-5-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_3-5) exten => s,12,Return() exten => _sw-5-.,10,Voicemail(u${ext}) exten => _sw-5-.,11,Goto(s,11) exten => sw-5-,10,Goto(sw-5-.,10) exten => sw-5-NOANSWER,10,Voicemail(u${ext}) exten => sw-5-NOANSWER,11,Goto(s,11) exten => sw-5-ANSWER,10,Goto(s,11) exten => sw-5-BUSY,10,Voicemail(b${ext}) exten => sw-5-BUSY,11,Goto(s,11) exten => sw-5-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-5-DONTCALL,11,Goto(s,11) exten => sw-5-TORTURE,10,Goto(${torcont},s,begin) exten => sw-5-TORTURE,11,Goto(s,11) [std-priv-exten_4] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-6-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_4-6) exten => s,12,Return() exten => _sw-6-.,10,Voicemail(u${ext}) exten => _sw-6-.,11,Goto(s,11) exten => sw-6-,10,Goto(sw-6-.,10) exten => sw-6-NOANSWER,10,Voicemail(u${ext}) exten => sw-6-NOANSWER,11,Goto(s,11) exten => sw-6-ANSWER,10,Goto(s,11) exten => sw-6-BUSY,10,Voicemail(b${ext}) exten => sw-6-BUSY,11,Goto(s,11) exten => sw-6-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-6-DONTCALL,11,Goto(s,11) exten => sw-6-TORTURE,10,Goto(${torcont},s,begin) exten => sw-6-TORTURE,11,Goto(s,11) [std-priv-exten_5] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-7-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_5-7) exten => s,12,Return() exten => _sw-7-.,10,Voicemail(u${ext}) exten => _sw-7-.,11,Goto(s,11) exten => sw-7-,10,Goto(sw-7-.,10) exten => sw-7-NOANSWER,10,Voicemail(u${ext}) exten => sw-7-NOANSWER,11,Goto(s,11) exten => sw-7-ANSWER,10,Goto(s,11) exten => sw-7-BUSY,10,Voicemail(b${ext}) exten => sw-7-BUSY,11,Goto(s,11) exten => sw-7-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-7-DONTCALL,11,Goto(s,11) exten => sw-7-TORTURE,10,Goto(${torcont},s,begin) exten => sw-7-TORTURE,11,Goto(s,11) [std-priv-exten_6] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-8-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_6-8) exten => s,12,Return() exten => _sw-8-.,10,Voicemail(u${ext}) exten => _sw-8-.,11,Goto(s,11) exten => sw-8-,10,Goto(sw-8-.,10) exten => sw-8-NOANSWER,10,Voicemail(u${ext}) exten => sw-8-NOANSWER,11,Goto(s,11) exten => sw-8-ANSWER,10,Goto(s,11) exten => sw-8-BUSY,10,Voicemail(b${ext}) exten => sw-8-BUSY,11,Goto(s,11) exten => sw-8-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-8-DONTCALL,11,Goto(s,11) exten => sw-8-TORTURE,10,Goto(${torcont},s,begin) exten => sw-8-TORTURE,11,Goto(s,11) [std-priv-exten_7] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-9-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_7-9) exten => s,12,Return() exten => _sw-9-.,10,Voicemail(u${ext}) exten => _sw-9-.,11,Goto(s,11) exten => sw-9-,10,Goto(sw-9-.,10) exten => sw-9-NOANSWER,10,Voicemail(u${ext}) exten => sw-9-NOANSWER,11,Goto(s,11) exten => sw-9-ANSWER,10,Goto(s,11) exten => sw-9-BUSY,10,Voicemail(b${ext}) exten => sw-9-BUSY,11,Goto(s,11) exten => sw-9-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-9-DONTCALL,11,Goto(s,11) exten => sw-9-TORTURE,10,Goto(${torcont},s,begin) exten => sw-9-TORTURE,11,Goto(s,11) [std-priv-exten_8] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-10-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_8-10) exten => s,12,Return() exten => _sw-10-.,10,Voicemail(u${ext}) exten => _sw-10-.,11,Goto(s,11) exten => sw-10-,10,Goto(sw-10-.,10) exten => sw-10-NOANSWER,10,Voicemail(u${ext}) exten => sw-10-NOANSWER,11,Goto(s,11) exten => sw-10-ANSWER,10,Goto(s,11) exten => sw-10-BUSY,10,Voicemail(b${ext}) exten => sw-10-BUSY,11,Goto(s,11) exten => sw-10-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-10-DONTCALL,11,Goto(s,11) exten => sw-10-TORTURE,10,Goto(${torcont},s,begin) exten => sw-10-TORTURE,11,Goto(s,11) [std-priv-exten_9] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-11-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_9-11) exten => s,12,Return() exten => _sw-11-.,10,Voicemail(u${ext}) exten => _sw-11-.,11,Goto(s,11) exten => sw-11-,10,Goto(sw-11-.,10) exten => sw-11-NOANSWER,10,Voicemail(u${ext}) exten => sw-11-NOANSWER,11,Goto(s,11) exten => sw-11-ANSWER,10,Goto(s,11) exten => sw-11-BUSY,10,Voicemail(b${ext}) exten => sw-11-BUSY,11,Goto(s,11) exten => sw-11-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-11-DONTCALL,11,Goto(s,11) exten => sw-11-TORTURE,10,Goto(${torcont},s,begin) exten => sw-11-TORTURE,11,Goto(s,11) [std-priv-exten_10] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-12-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_10-12) exten => s,12,Return() exten => _sw-12-.,10,Voicemail(u${ext}) exten => _sw-12-.,11,Goto(s,11) exten => sw-12-,10,Goto(sw-12-.,10) exten => sw-12-NOANSWER,10,Voicemail(u${ext}) exten => sw-12-NOANSWER,11,Goto(s,11) exten => sw-12-ANSWER,10,Goto(s,11) exten => sw-12-BUSY,10,Voicemail(b${ext}) exten => sw-12-BUSY,11,Goto(s,11) exten => sw-12-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-12-DONTCALL,11,Goto(s,11) exten => sw-12-TORTURE,10,Goto(${torcont},s,begin) exten => sw-12-TORTURE,11,Goto(s,11) [std-priv-exten_11] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-13-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_11-13) exten => s,12,Return() exten => _sw-13-.,10,Voicemail(u${ext}) exten => _sw-13-.,11,Goto(s,11) exten => sw-13-,10,Goto(sw-13-.,10) exten => sw-13-NOANSWER,10,Voicemail(u${ext}) exten => sw-13-NOANSWER,11,Goto(s,11) exten => sw-13-ANSWER,10,Goto(s,11) exten => sw-13-BUSY,10,Voicemail(b${ext}) exten => sw-13-BUSY,11,Goto(s,11) exten => sw-13-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-13-DONTCALL,11,Goto(s,11) exten => sw-13-TORTURE,10,Goto(${torcont},s,begin) exten => sw-13-TORTURE,11,Goto(s,11) [std-priv-exten_12] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-14-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_12-14) exten => s,12,Return() exten => _sw-14-.,10,Voicemail(u${ext}) exten => _sw-14-.,11,Goto(s,11) exten => sw-14-,10,Goto(sw-14-.,10) exten => sw-14-NOANSWER,10,Voicemail(u${ext}) exten => sw-14-NOANSWER,11,Goto(s,11) exten => sw-14-ANSWER,10,Goto(s,11) exten => sw-14-BUSY,10,Voicemail(b${ext}) exten => sw-14-BUSY,11,Goto(s,11) exten => sw-14-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-14-DONTCALL,11,Goto(s,11) exten => sw-14-TORTURE,10,Goto(${torcont},s,begin) exten => sw-14-TORTURE,11,Goto(s,11) [std-priv-exten_13] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-15-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_13-15) exten => s,12,Return() exten => _sw-15-.,10,Voicemail(u${ext}) exten => _sw-15-.,11,Goto(s,11) exten => sw-15-,10,Goto(sw-15-.,10) exten => sw-15-NOANSWER,10,Voicemail(u${ext}) exten => sw-15-NOANSWER,11,Goto(s,11) exten => sw-15-ANSWER,10,Goto(s,11) exten => sw-15-BUSY,10,Voicemail(b${ext}) exten => sw-15-BUSY,11,Goto(s,11) exten => sw-15-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-15-DONTCALL,11,Goto(s,11) exten => sw-15-TORTURE,10,Goto(${torcont},s,begin) exten => sw-15-TORTURE,11,Goto(s,11) [std-priv-exten_14] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-16-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_14-16) exten => s,12,Return() exten => _sw-16-.,10,Voicemail(u${ext}) exten => _sw-16-.,11,Goto(s,11) exten => sw-16-,10,Goto(sw-16-.,10) exten => sw-16-NOANSWER,10,Voicemail(u${ext}) exten => sw-16-NOANSWER,11,Goto(s,11) exten => sw-16-ANSWER,10,Goto(s,11) exten => sw-16-BUSY,10,Voicemail(b${ext}) exten => sw-16-BUSY,11,Goto(s,11) exten => sw-16-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-16-DONTCALL,11,Goto(s,11) exten => sw-16-TORTURE,10,Goto(${torcont},s,begin) exten => sw-16-TORTURE,11,Goto(s,11) [std-priv-exten_15] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-17-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_15-17) exten => s,12,Return() exten => _sw-17-.,10,Voicemail(u${ext}) exten => _sw-17-.,11,Goto(s,11) exten => sw-17-,10,Goto(sw-17-.,10) exten => sw-17-NOANSWER,10,Voicemail(u${ext}) exten => sw-17-NOANSWER,11,Goto(s,11) exten => sw-17-ANSWER,10,Goto(s,11) exten => sw-17-BUSY,10,Voicemail(b${ext}) exten => sw-17-BUSY,11,Goto(s,11) exten => sw-17-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-17-DONTCALL,11,Goto(s,11) exten => sw-17-TORTURE,10,Goto(${torcont},s,begin) exten => sw-17-TORTURE,11,Goto(s,11) [std-priv-exten_16] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-18-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_16-18) exten => s,12,Return() exten => _sw-18-.,10,Voicemail(u${ext}) exten => _sw-18-.,11,Goto(s,11) exten => sw-18-,10,Goto(sw-18-.,10) exten => sw-18-NOANSWER,10,Voicemail(u${ext}) exten => sw-18-NOANSWER,11,Goto(s,11) exten => sw-18-ANSWER,10,Goto(s,11) exten => sw-18-BUSY,10,Voicemail(b${ext}) exten => sw-18-BUSY,11,Goto(s,11) exten => sw-18-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-18-DONTCALL,11,Goto(s,11) exten => sw-18-TORTURE,10,Goto(${torcont},s,begin) exten => sw-18-TORTURE,11,Goto(s,11) [std-priv-exten_17] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-19-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_17-19) exten => s,12,Return() exten => _sw-19-.,10,Voicemail(u${ext}) exten => _sw-19-.,11,Goto(s,11) exten => sw-19-,10,Goto(sw-19-.,10) exten => sw-19-NOANSWER,10,Voicemail(u${ext}) exten => sw-19-NOANSWER,11,Goto(s,11) exten => sw-19-ANSWER,10,Goto(s,11) exten => sw-19-BUSY,10,Voicemail(b${ext}) exten => sw-19-BUSY,11,Goto(s,11) exten => sw-19-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-19-DONTCALL,11,Goto(s,11) exten => sw-19-TORTURE,10,Goto(${torcont},s,begin) exten => sw-19-TORTURE,11,Goto(s,11) [std-priv-exten_18] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-20-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_18-20) exten => s,12,Return() exten => _sw-20-.,10,Voicemail(u${ext}) exten => _sw-20-.,11,Goto(s,11) exten => sw-20-,10,Goto(sw-20-.,10) exten => sw-20-NOANSWER,10,Voicemail(u${ext}) exten => sw-20-NOANSWER,11,Goto(s,11) exten => sw-20-ANSWER,10,Goto(s,11) exten => sw-20-BUSY,10,Voicemail(b${ext}) exten => sw-20-BUSY,11,Goto(s,11) exten => sw-20-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-20-DONTCALL,11,Goto(s,11) exten => sw-20-TORTURE,10,Goto(${torcont},s,begin) exten => sw-20-TORTURE,11,Goto(s,11) [std-priv-exten_19] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-21-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_19-21) exten => s,12,Return() exten => _sw-21-.,10,Voicemail(u${ext}) exten => _sw-21-.,11,Goto(s,11) exten => sw-21-,10,Goto(sw-21-.,10) exten => sw-21-NOANSWER,10,Voicemail(u${ext}) exten => sw-21-NOANSWER,11,Goto(s,11) exten => sw-21-ANSWER,10,Goto(s,11) exten => sw-21-BUSY,10,Voicemail(b${ext}) exten => sw-21-BUSY,11,Goto(s,11) exten => sw-21-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-21-DONTCALL,11,Goto(s,11) exten => sw-21-TORTURE,10,Goto(${torcont},s,begin) exten => sw-21-TORTURE,11,Goto(s,11) [std-priv-exten_20] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-22-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_20-22) exten => s,12,Return() exten => _sw-22-.,10,Voicemail(u${ext}) exten => _sw-22-.,11,Goto(s,11) exten => sw-22-,10,Goto(sw-22-.,10) exten => sw-22-NOANSWER,10,Voicemail(u${ext}) exten => sw-22-NOANSWER,11,Goto(s,11) exten => sw-22-ANSWER,10,Goto(s,11) exten => sw-22-BUSY,10,Voicemail(b${ext}) exten => sw-22-BUSY,11,Goto(s,11) exten => sw-22-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-22-DONTCALL,11,Goto(s,11) exten => sw-22-TORTURE,10,Goto(${torcont},s,begin) exten => sw-22-TORTURE,11,Goto(s,11) [std-priv-exten_21] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-23-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_21-23) exten => s,12,Return() exten => _sw-23-.,10,Voicemail(u${ext}) exten => _sw-23-.,11,Goto(s,11) exten => sw-23-,10,Goto(sw-23-.,10) exten => sw-23-NOANSWER,10,Voicemail(u${ext}) exten => sw-23-NOANSWER,11,Goto(s,11) exten => sw-23-ANSWER,10,Goto(s,11) exten => sw-23-BUSY,10,Voicemail(b${ext}) exten => sw-23-BUSY,11,Goto(s,11) exten => sw-23-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-23-DONTCALL,11,Goto(s,11) exten => sw-23-TORTURE,10,Goto(${torcont},s,begin) exten => sw-23-TORTURE,11,Goto(s,11) [std-priv-exten_22] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-24-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_22-24) exten => s,12,Return() exten => _sw-24-.,10,Voicemail(u${ext}) exten => _sw-24-.,11,Goto(s,11) exten => sw-24-,10,Goto(sw-24-.,10) exten => sw-24-NOANSWER,10,Voicemail(u${ext}) exten => sw-24-NOANSWER,11,Goto(s,11) exten => sw-24-ANSWER,10,Goto(s,11) exten => sw-24-BUSY,10,Voicemail(b${ext}) exten => sw-24-BUSY,11,Goto(s,11) exten => sw-24-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-24-DONTCALL,11,Goto(s,11) exten => sw-24-TORTURE,10,Goto(${torcont},s,begin) exten => sw-24-TORTURE,11,Goto(s,11) [std-priv-exten_23] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-25-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_23-25) exten => s,12,Return() exten => _sw-25-.,10,Voicemail(u${ext}) exten => _sw-25-.,11,Goto(s,11) exten => sw-25-,10,Goto(sw-25-.,10) exten => sw-25-NOANSWER,10,Voicemail(u${ext}) exten => sw-25-NOANSWER,11,Goto(s,11) exten => sw-25-ANSWER,10,Goto(s,11) exten => sw-25-BUSY,10,Voicemail(b${ext}) exten => sw-25-BUSY,11,Goto(s,11) exten => sw-25-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-25-DONTCALL,11,Goto(s,11) exten => sw-25-TORTURE,10,Goto(${torcont},s,begin) exten => sw-25-TORTURE,11,Goto(s,11) [std-priv-exten_24] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-26-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_24-26) exten => s,12,Return() exten => _sw-26-.,10,Voicemail(u${ext}) exten => _sw-26-.,11,Goto(s,11) exten => sw-26-,10,Goto(sw-26-.,10) exten => sw-26-NOANSWER,10,Voicemail(u${ext}) exten => sw-26-NOANSWER,11,Goto(s,11) exten => sw-26-ANSWER,10,Goto(s,11) exten => sw-26-BUSY,10,Voicemail(b${ext}) exten => sw-26-BUSY,11,Goto(s,11) exten => sw-26-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-26-DONTCALL,11,Goto(s,11) exten => sw-26-TORTURE,10,Goto(${torcont},s,begin) exten => sw-26-TORTURE,11,Goto(s,11) [std-priv-exten_25] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-27-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_25-27) exten => s,12,Return() exten => _sw-27-.,10,Voicemail(u${ext}) exten => _sw-27-.,11,Goto(s,11) exten => sw-27-,10,Goto(sw-27-.,10) exten => sw-27-NOANSWER,10,Voicemail(u${ext}) exten => sw-27-NOANSWER,11,Goto(s,11) exten => sw-27-ANSWER,10,Goto(s,11) exten => sw-27-BUSY,10,Voicemail(b${ext}) exten => sw-27-BUSY,11,Goto(s,11) exten => sw-27-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-27-DONTCALL,11,Goto(s,11) exten => sw-27-TORTURE,10,Goto(${torcont},s,begin) exten => sw-27-TORTURE,11,Goto(s,11) [std-priv-exten_26] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-28-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_26-28) exten => s,12,Return() exten => _sw-28-.,10,Voicemail(u${ext}) exten => _sw-28-.,11,Goto(s,11) exten => sw-28-,10,Goto(sw-28-.,10) exten => sw-28-NOANSWER,10,Voicemail(u${ext}) exten => sw-28-NOANSWER,11,Goto(s,11) exten => sw-28-ANSWER,10,Goto(s,11) exten => sw-28-BUSY,10,Voicemail(b${ext}) exten => sw-28-BUSY,11,Goto(s,11) exten => sw-28-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-28-DONTCALL,11,Goto(s,11) exten => sw-28-TORTURE,10,Goto(${torcont},s,begin) exten => sw-28-TORTURE,11,Goto(s,11) [std-priv-exten_27] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-29-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_27-29) exten => s,12,Return() exten => _sw-29-.,10,Voicemail(u${ext}) exten => _sw-29-.,11,Goto(s,11) exten => sw-29-,10,Goto(sw-29-.,10) exten => sw-29-NOANSWER,10,Voicemail(u${ext}) exten => sw-29-NOANSWER,11,Goto(s,11) exten => sw-29-ANSWER,10,Goto(s,11) exten => sw-29-BUSY,10,Voicemail(b${ext}) exten => sw-29-BUSY,11,Goto(s,11) exten => sw-29-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-29-DONTCALL,11,Goto(s,11) exten => sw-29-TORTURE,10,Goto(${torcont},s,begin) exten => sw-29-TORTURE,11,Goto(s,11) [std-priv-exten_28] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-30-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_28-30) exten => s,12,Return() exten => _sw-30-.,10,Voicemail(u${ext}) exten => _sw-30-.,11,Goto(s,11) exten => sw-30-,10,Goto(sw-30-.,10) exten => sw-30-NOANSWER,10,Voicemail(u${ext}) exten => sw-30-NOANSWER,11,Goto(s,11) exten => sw-30-ANSWER,10,Goto(s,11) exten => sw-30-BUSY,10,Voicemail(b${ext}) exten => sw-30-BUSY,11,Goto(s,11) exten => sw-30-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-30-DONTCALL,11,Goto(s,11) exten => sw-30-TORTURE,10,Goto(${torcont},s,begin) exten => sw-30-TORTURE,11,Goto(s,11) [std-priv-exten_29] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-31-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_29-31) exten => s,12,Return() exten => _sw-31-.,10,Voicemail(u${ext}) exten => _sw-31-.,11,Goto(s,11) exten => sw-31-,10,Goto(sw-31-.,10) exten => sw-31-NOANSWER,10,Voicemail(u${ext}) exten => sw-31-NOANSWER,11,Goto(s,11) exten => sw-31-ANSWER,10,Goto(s,11) exten => sw-31-BUSY,10,Voicemail(b${ext}) exten => sw-31-BUSY,11,Goto(s,11) exten => sw-31-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-31-DONTCALL,11,Goto(s,11) exten => sw-31-TORTURE,10,Goto(${torcont},s,begin) exten => sw-31-TORTURE,11,Goto(s,11) [std-priv-exten_30] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-32-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_30-32) exten => s,12,Return() exten => _sw-32-.,10,Voicemail(u${ext}) exten => _sw-32-.,11,Goto(s,11) exten => sw-32-,10,Goto(sw-32-.,10) exten => sw-32-NOANSWER,10,Voicemail(u${ext}) exten => sw-32-NOANSWER,11,Goto(s,11) exten => sw-32-ANSWER,10,Goto(s,11) exten => sw-32-BUSY,10,Voicemail(b${ext}) exten => sw-32-BUSY,11,Goto(s,11) exten => sw-32-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-32-DONTCALL,11,Goto(s,11) exten => sw-32-TORTURE,10,Goto(${torcont},s,begin) exten => sw-32-TORTURE,11,Goto(s,11) [std-priv-exten_31] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-33-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_31-33) exten => s,12,Return() exten => _sw-33-.,10,Voicemail(u${ext}) exten => _sw-33-.,11,Goto(s,11) exten => sw-33-,10,Goto(sw-33-.,10) exten => sw-33-NOANSWER,10,Voicemail(u${ext}) exten => sw-33-NOANSWER,11,Goto(s,11) exten => sw-33-ANSWER,10,Goto(s,11) exten => sw-33-BUSY,10,Voicemail(b${ext}) exten => sw-33-BUSY,11,Goto(s,11) exten => sw-33-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-33-DONTCALL,11,Goto(s,11) exten => sw-33-TORTURE,10,Goto(${torcont},s,begin) exten => sw-33-TORTURE,11,Goto(s,11) [std-priv-exten_32] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-34-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_32-34) exten => s,12,Return() exten => _sw-34-.,10,Voicemail(u${ext}) exten => _sw-34-.,11,Goto(s,11) exten => sw-34-,10,Goto(sw-34-.,10) exten => sw-34-NOANSWER,10,Voicemail(u${ext}) exten => sw-34-NOANSWER,11,Goto(s,11) exten => sw-34-ANSWER,10,Goto(s,11) exten => sw-34-BUSY,10,Voicemail(b${ext}) exten => sw-34-BUSY,11,Goto(s,11) exten => sw-34-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-34-DONTCALL,11,Goto(s,11) exten => sw-34-TORTURE,10,Goto(${torcont},s,begin) exten => sw-34-TORTURE,11,Goto(s,11) [std-priv-exten_33] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-35-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_33-35) exten => s,12,Return() exten => _sw-35-.,10,Voicemail(u${ext}) exten => _sw-35-.,11,Goto(s,11) exten => sw-35-,10,Goto(sw-35-.,10) exten => sw-35-NOANSWER,10,Voicemail(u${ext}) exten => sw-35-NOANSWER,11,Goto(s,11) exten => sw-35-ANSWER,10,Goto(s,11) exten => sw-35-BUSY,10,Voicemail(b${ext}) exten => sw-35-BUSY,11,Goto(s,11) exten => sw-35-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-35-DONTCALL,11,Goto(s,11) exten => sw-35-TORTURE,10,Goto(${torcont},s,begin) exten => sw-35-TORTURE,11,Goto(s,11) [std-priv-exten_34] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-36-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_34-36) exten => s,12,Return() exten => _sw-36-.,10,Voicemail(u${ext}) exten => _sw-36-.,11,Goto(s,11) exten => sw-36-,10,Goto(sw-36-.,10) exten => sw-36-NOANSWER,10,Voicemail(u${ext}) exten => sw-36-NOANSWER,11,Goto(s,11) exten => sw-36-ANSWER,10,Goto(s,11) exten => sw-36-BUSY,10,Voicemail(b${ext}) exten => sw-36-BUSY,11,Goto(s,11) exten => sw-36-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-36-DONTCALL,11,Goto(s,11) exten => sw-36-TORTURE,10,Goto(${torcont},s,begin) exten => sw-36-TORTURE,11,Goto(s,11) [std-priv-exten_35] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-37-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_35-37) exten => s,12,Return() exten => _sw-37-.,10,Voicemail(u${ext}) exten => _sw-37-.,11,Goto(s,11) exten => sw-37-,10,Goto(sw-37-.,10) exten => sw-37-NOANSWER,10,Voicemail(u${ext}) exten => sw-37-NOANSWER,11,Goto(s,11) exten => sw-37-ANSWER,10,Goto(s,11) exten => sw-37-BUSY,10,Voicemail(b${ext}) exten => sw-37-BUSY,11,Goto(s,11) exten => sw-37-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-37-DONTCALL,11,Goto(s,11) exten => sw-37-TORTURE,10,Goto(${torcont},s,begin) exten => sw-37-TORTURE,11,Goto(s,11) [std-priv-exten_36] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-38-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_36-38) exten => s,12,Return() exten => _sw-38-.,10,Voicemail(u${ext}) exten => _sw-38-.,11,Goto(s,11) exten => sw-38-,10,Goto(sw-38-.,10) exten => sw-38-NOANSWER,10,Voicemail(u${ext}) exten => sw-38-NOANSWER,11,Goto(s,11) exten => sw-38-ANSWER,10,Goto(s,11) exten => sw-38-BUSY,10,Voicemail(b${ext}) exten => sw-38-BUSY,11,Goto(s,11) exten => sw-38-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-38-DONTCALL,11,Goto(s,11) exten => sw-38-TORTURE,10,Goto(${torcont},s,begin) exten => sw-38-TORTURE,11,Goto(s,11) [std-priv-exten_37] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-39-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_37-39) exten => s,12,Return() exten => _sw-39-.,10,Voicemail(u${ext}) exten => _sw-39-.,11,Goto(s,11) exten => sw-39-,10,Goto(sw-39-.,10) exten => sw-39-NOANSWER,10,Voicemail(u${ext}) exten => sw-39-NOANSWER,11,Goto(s,11) exten => sw-39-ANSWER,10,Goto(s,11) exten => sw-39-BUSY,10,Voicemail(b${ext}) exten => sw-39-BUSY,11,Goto(s,11) exten => sw-39-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-39-DONTCALL,11,Goto(s,11) exten => sw-39-TORTURE,10,Goto(${torcont},s,begin) exten => sw-39-TORTURE,11,Goto(s,11) [std-priv-exten_38] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-40-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_38-40) exten => s,12,Return() exten => _sw-40-.,10,Voicemail(u${ext}) exten => _sw-40-.,11,Goto(s,11) exten => sw-40-,10,Goto(sw-40-.,10) exten => sw-40-NOANSWER,10,Voicemail(u${ext}) exten => sw-40-NOANSWER,11,Goto(s,11) exten => sw-40-ANSWER,10,Goto(s,11) exten => sw-40-BUSY,10,Voicemail(b${ext}) exten => sw-40-BUSY,11,Goto(s,11) exten => sw-40-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-40-DONTCALL,11,Goto(s,11) exten => sw-40-TORTURE,10,Goto(${torcont},s,begin) exten => sw-40-TORTURE,11,Goto(s,11) [std-priv-exten_39] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-41-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_39-41) exten => s,12,Return() exten => _sw-41-.,10,Voicemail(u${ext}) exten => _sw-41-.,11,Goto(s,11) exten => sw-41-,10,Goto(sw-41-.,10) exten => sw-41-NOANSWER,10,Voicemail(u${ext}) exten => sw-41-NOANSWER,11,Goto(s,11) exten => sw-41-ANSWER,10,Goto(s,11) exten => sw-41-BUSY,10,Voicemail(b${ext}) exten => sw-41-BUSY,11,Goto(s,11) exten => sw-41-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-41-DONTCALL,11,Goto(s,11) exten => sw-41-TORTURE,10,Goto(${torcont},s,begin) exten => sw-41-TORTURE,11,Goto(s,11) [std-priv-exten_40] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-42-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_40-42) exten => s,12,Return() exten => _sw-42-.,10,Voicemail(u${ext}) exten => _sw-42-.,11,Goto(s,11) exten => sw-42-,10,Goto(sw-42-.,10) exten => sw-42-NOANSWER,10,Voicemail(u${ext}) exten => sw-42-NOANSWER,11,Goto(s,11) exten => sw-42-ANSWER,10,Goto(s,11) exten => sw-42-BUSY,10,Voicemail(b${ext}) exten => sw-42-BUSY,11,Goto(s,11) exten => sw-42-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-42-DONTCALL,11,Goto(s,11) exten => sw-42-TORTURE,10,Goto(${torcont},s,begin) exten => sw-42-TORTURE,11,Goto(s,11) [std-priv-exten_41] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-43-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_41-43) exten => s,12,Return() exten => _sw-43-.,10,Voicemail(u${ext}) exten => _sw-43-.,11,Goto(s,11) exten => sw-43-,10,Goto(sw-43-.,10) exten => sw-43-NOANSWER,10,Voicemail(u${ext}) exten => sw-43-NOANSWER,11,Goto(s,11) exten => sw-43-ANSWER,10,Goto(s,11) exten => sw-43-BUSY,10,Voicemail(b${ext}) exten => sw-43-BUSY,11,Goto(s,11) exten => sw-43-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-43-DONTCALL,11,Goto(s,11) exten => sw-43-TORTURE,10,Goto(${torcont},s,begin) exten => sw-43-TORTURE,11,Goto(s,11) [std-priv-exten_42] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-44-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_42-44) exten => s,12,Return() exten => _sw-44-.,10,Voicemail(u${ext}) exten => _sw-44-.,11,Goto(s,11) exten => sw-44-,10,Goto(sw-44-.,10) exten => sw-44-NOANSWER,10,Voicemail(u${ext}) exten => sw-44-NOANSWER,11,Goto(s,11) exten => sw-44-ANSWER,10,Goto(s,11) exten => sw-44-BUSY,10,Voicemail(b${ext}) exten => sw-44-BUSY,11,Goto(s,11) exten => sw-44-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-44-DONTCALL,11,Goto(s,11) exten => sw-44-TORTURE,10,Goto(${torcont},s,begin) exten => sw-44-TORTURE,11,Goto(s,11) [std-priv-exten_43] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-45-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_43-45) exten => s,12,Return() exten => _sw-45-.,10,Voicemail(u${ext}) exten => _sw-45-.,11,Goto(s,11) exten => sw-45-,10,Goto(sw-45-.,10) exten => sw-45-NOANSWER,10,Voicemail(u${ext}) exten => sw-45-NOANSWER,11,Goto(s,11) exten => sw-45-ANSWER,10,Goto(s,11) exten => sw-45-BUSY,10,Voicemail(b${ext}) exten => sw-45-BUSY,11,Goto(s,11) exten => sw-45-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-45-DONTCALL,11,Goto(s,11) exten => sw-45-TORTURE,10,Goto(${torcont},s,begin) exten => sw-45-TORTURE,11,Goto(s,11) [std-priv-exten_44] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-46-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_44-46) exten => s,12,Return() exten => _sw-46-.,10,Voicemail(u${ext}) exten => _sw-46-.,11,Goto(s,11) exten => sw-46-,10,Goto(sw-46-.,10) exten => sw-46-NOANSWER,10,Voicemail(u${ext}) exten => sw-46-NOANSWER,11,Goto(s,11) exten => sw-46-ANSWER,10,Goto(s,11) exten => sw-46-BUSY,10,Voicemail(b${ext}) exten => sw-46-BUSY,11,Goto(s,11) exten => sw-46-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-46-DONTCALL,11,Goto(s,11) exten => sw-46-TORTURE,10,Goto(${torcont},s,begin) exten => sw-46-TORTURE,11,Goto(s,11) [std-priv-exten_45] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-47-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_45-47) exten => s,12,Return() exten => _sw-47-.,10,Voicemail(u${ext}) exten => _sw-47-.,11,Goto(s,11) exten => sw-47-,10,Goto(sw-47-.,10) exten => sw-47-NOANSWER,10,Voicemail(u${ext}) exten => sw-47-NOANSWER,11,Goto(s,11) exten => sw-47-ANSWER,10,Goto(s,11) exten => sw-47-BUSY,10,Voicemail(b${ext}) exten => sw-47-BUSY,11,Goto(s,11) exten => sw-47-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-47-DONTCALL,11,Goto(s,11) exten => sw-47-TORTURE,10,Goto(${torcont},s,begin) exten => sw-47-TORTURE,11,Goto(s,11) [std-priv-exten_46] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-48-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_46-48) exten => s,12,Return() exten => _sw-48-.,10,Voicemail(u${ext}) exten => _sw-48-.,11,Goto(s,11) exten => sw-48-,10,Goto(sw-48-.,10) exten => sw-48-NOANSWER,10,Voicemail(u${ext}) exten => sw-48-NOANSWER,11,Goto(s,11) exten => sw-48-ANSWER,10,Goto(s,11) exten => sw-48-BUSY,10,Voicemail(b${ext}) exten => sw-48-BUSY,11,Goto(s,11) exten => sw-48-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-48-DONTCALL,11,Goto(s,11) exten => sw-48-TORTURE,10,Goto(${torcont},s,begin) exten => sw-48-TORTURE,11,Goto(s,11) [std-priv-exten_47] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-49-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_47-49) exten => s,12,Return() exten => _sw-49-.,10,Voicemail(u${ext}) exten => _sw-49-.,11,Goto(s,11) exten => sw-49-,10,Goto(sw-49-.,10) exten => sw-49-NOANSWER,10,Voicemail(u${ext}) exten => sw-49-NOANSWER,11,Goto(s,11) exten => sw-49-ANSWER,10,Goto(s,11) exten => sw-49-BUSY,10,Voicemail(b${ext}) exten => sw-49-BUSY,11,Goto(s,11) exten => sw-49-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-49-DONTCALL,11,Goto(s,11) exten => sw-49-TORTURE,10,Goto(${torcont},s,begin) exten => sw-49-TORTURE,11,Goto(s,11) [std-priv-exten_48] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-50-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_48-50) exten => s,12,Return() exten => _sw-50-.,10,Voicemail(u${ext}) exten => _sw-50-.,11,Goto(s,11) exten => sw-50-,10,Goto(sw-50-.,10) exten => sw-50-NOANSWER,10,Voicemail(u${ext}) exten => sw-50-NOANSWER,11,Goto(s,11) exten => sw-50-ANSWER,10,Goto(s,11) exten => sw-50-BUSY,10,Voicemail(b${ext}) exten => sw-50-BUSY,11,Goto(s,11) exten => sw-50-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-50-DONTCALL,11,Goto(s,11) exten => sw-50-TORTURE,10,Goto(${torcont},s,begin) exten => sw-50-TORTURE,11,Goto(s,11) [std-priv-exten_49] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-51-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_49-51) exten => s,12,Return() exten => _sw-51-.,10,Voicemail(u${ext}) exten => _sw-51-.,11,Goto(s,11) exten => sw-51-,10,Goto(sw-51-.,10) exten => sw-51-NOANSWER,10,Voicemail(u${ext}) exten => sw-51-NOANSWER,11,Goto(s,11) exten => sw-51-ANSWER,10,Goto(s,11) exten => sw-51-BUSY,10,Voicemail(b${ext}) exten => sw-51-BUSY,11,Goto(s,11) exten => sw-51-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-51-DONTCALL,11,Goto(s,11) exten => sw-51-TORTURE,10,Goto(${torcont},s,begin) exten => sw-51-TORTURE,11,Goto(s,11) [std-priv-exten_50] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-52-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_50-52) exten => s,12,Return() exten => _sw-52-.,10,Voicemail(u${ext}) exten => _sw-52-.,11,Goto(s,11) exten => sw-52-,10,Goto(sw-52-.,10) exten => sw-52-NOANSWER,10,Voicemail(u${ext}) exten => sw-52-NOANSWER,11,Goto(s,11) exten => sw-52-ANSWER,10,Goto(s,11) exten => sw-52-BUSY,10,Voicemail(b${ext}) exten => sw-52-BUSY,11,Goto(s,11) exten => sw-52-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-52-DONTCALL,11,Goto(s,11) exten => sw-52-TORTURE,10,Goto(${torcont},s,begin) exten => sw-52-TORTURE,11,Goto(s,11) [std-priv-exten_51] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-53-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_51-53) exten => s,12,Return() exten => _sw-53-.,10,Voicemail(u${ext}) exten => _sw-53-.,11,Goto(s,11) exten => sw-53-,10,Goto(sw-53-.,10) exten => sw-53-NOANSWER,10,Voicemail(u${ext}) exten => sw-53-NOANSWER,11,Goto(s,11) exten => sw-53-ANSWER,10,Goto(s,11) exten => sw-53-BUSY,10,Voicemail(b${ext}) exten => sw-53-BUSY,11,Goto(s,11) exten => sw-53-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-53-DONTCALL,11,Goto(s,11) exten => sw-53-TORTURE,10,Goto(${torcont},s,begin) exten => sw-53-TORTURE,11,Goto(s,11) [std-priv-exten_52] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-54-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_52-54) exten => s,12,Return() exten => _sw-54-.,10,Voicemail(u${ext}) exten => _sw-54-.,11,Goto(s,11) exten => sw-54-,10,Goto(sw-54-.,10) exten => sw-54-NOANSWER,10,Voicemail(u${ext}) exten => sw-54-NOANSWER,11,Goto(s,11) exten => sw-54-ANSWER,10,Goto(s,11) exten => sw-54-BUSY,10,Voicemail(b${ext}) exten => sw-54-BUSY,11,Goto(s,11) exten => sw-54-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-54-DONTCALL,11,Goto(s,11) exten => sw-54-TORTURE,10,Goto(${torcont},s,begin) exten => sw-54-TORTURE,11,Goto(s,11) [std-priv-exten_53] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-55-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_53-55) exten => s,12,Return() exten => _sw-55-.,10,Voicemail(u${ext}) exten => _sw-55-.,11,Goto(s,11) exten => sw-55-,10,Goto(sw-55-.,10) exten => sw-55-NOANSWER,10,Voicemail(u${ext}) exten => sw-55-NOANSWER,11,Goto(s,11) exten => sw-55-ANSWER,10,Goto(s,11) exten => sw-55-BUSY,10,Voicemail(b${ext}) exten => sw-55-BUSY,11,Goto(s,11) exten => sw-55-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-55-DONTCALL,11,Goto(s,11) exten => sw-55-TORTURE,10,Goto(${torcont},s,begin) exten => sw-55-TORTURE,11,Goto(s,11) [std-priv-exten_54] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-56-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_54-56) exten => s,12,Return() exten => _sw-56-.,10,Voicemail(u${ext}) exten => _sw-56-.,11,Goto(s,11) exten => sw-56-,10,Goto(sw-56-.,10) exten => sw-56-NOANSWER,10,Voicemail(u${ext}) exten => sw-56-NOANSWER,11,Goto(s,11) exten => sw-56-ANSWER,10,Goto(s,11) exten => sw-56-BUSY,10,Voicemail(b${ext}) exten => sw-56-BUSY,11,Goto(s,11) exten => sw-56-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-56-DONTCALL,11,Goto(s,11) exten => sw-56-TORTURE,10,Goto(${torcont},s,begin) exten => sw-56-TORTURE,11,Goto(s,11) [std-priv-exten_55] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-57-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_55-57) exten => s,12,Return() exten => _sw-57-.,10,Voicemail(u${ext}) exten => _sw-57-.,11,Goto(s,11) exten => sw-57-,10,Goto(sw-57-.,10) exten => sw-57-NOANSWER,10,Voicemail(u${ext}) exten => sw-57-NOANSWER,11,Goto(s,11) exten => sw-57-ANSWER,10,Goto(s,11) exten => sw-57-BUSY,10,Voicemail(b${ext}) exten => sw-57-BUSY,11,Goto(s,11) exten => sw-57-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-57-DONTCALL,11,Goto(s,11) exten => sw-57-TORTURE,10,Goto(${torcont},s,begin) exten => sw-57-TORTURE,11,Goto(s,11) [std-priv-exten_56] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-58-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_56-58) exten => s,12,Return() exten => _sw-58-.,10,Voicemail(u${ext}) exten => _sw-58-.,11,Goto(s,11) exten => sw-58-,10,Goto(sw-58-.,10) exten => sw-58-NOANSWER,10,Voicemail(u${ext}) exten => sw-58-NOANSWER,11,Goto(s,11) exten => sw-58-ANSWER,10,Goto(s,11) exten => sw-58-BUSY,10,Voicemail(b${ext}) exten => sw-58-BUSY,11,Goto(s,11) exten => sw-58-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-58-DONTCALL,11,Goto(s,11) exten => sw-58-TORTURE,10,Goto(${torcont},s,begin) exten => sw-58-TORTURE,11,Goto(s,11) [std-priv-exten_57] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-59-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_57-59) exten => s,12,Return() exten => _sw-59-.,10,Voicemail(u${ext}) exten => _sw-59-.,11,Goto(s,11) exten => sw-59-,10,Goto(sw-59-.,10) exten => sw-59-NOANSWER,10,Voicemail(u${ext}) exten => sw-59-NOANSWER,11,Goto(s,11) exten => sw-59-ANSWER,10,Goto(s,11) exten => sw-59-BUSY,10,Voicemail(b${ext}) exten => sw-59-BUSY,11,Goto(s,11) exten => sw-59-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-59-DONTCALL,11,Goto(s,11) exten => sw-59-TORTURE,10,Goto(${torcont},s,begin) exten => sw-59-TORTURE,11,Goto(s,11) [std-priv-exten_58] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-60-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_58-60) exten => s,12,Return() exten => _sw-60-.,10,Voicemail(u${ext}) exten => _sw-60-.,11,Goto(s,11) exten => sw-60-,10,Goto(sw-60-.,10) exten => sw-60-NOANSWER,10,Voicemail(u${ext}) exten => sw-60-NOANSWER,11,Goto(s,11) exten => sw-60-ANSWER,10,Goto(s,11) exten => sw-60-BUSY,10,Voicemail(b${ext}) exten => sw-60-BUSY,11,Goto(s,11) exten => sw-60-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-60-DONTCALL,11,Goto(s,11) exten => sw-60-TORTURE,10,Goto(${torcont},s,begin) exten => sw-60-TORTURE,11,Goto(s,11) [std-priv-exten_59] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-61-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_59-61) exten => s,12,Return() exten => _sw-61-.,10,Voicemail(u${ext}) exten => _sw-61-.,11,Goto(s,11) exten => sw-61-,10,Goto(sw-61-.,10) exten => sw-61-NOANSWER,10,Voicemail(u${ext}) exten => sw-61-NOANSWER,11,Goto(s,11) exten => sw-61-ANSWER,10,Goto(s,11) exten => sw-61-BUSY,10,Voicemail(b${ext}) exten => sw-61-BUSY,11,Goto(s,11) exten => sw-61-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-61-DONTCALL,11,Goto(s,11) exten => sw-61-TORTURE,10,Goto(${torcont},s,begin) exten => sw-61-TORTURE,11,Goto(s,11) [std-priv-exten_60] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-62-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_60-62) exten => s,12,Return() exten => _sw-62-.,10,Voicemail(u${ext}) exten => _sw-62-.,11,Goto(s,11) exten => sw-62-,10,Goto(sw-62-.,10) exten => sw-62-NOANSWER,10,Voicemail(u${ext}) exten => sw-62-NOANSWER,11,Goto(s,11) exten => sw-62-ANSWER,10,Goto(s,11) exten => sw-62-BUSY,10,Voicemail(b${ext}) exten => sw-62-BUSY,11,Goto(s,11) exten => sw-62-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-62-DONTCALL,11,Goto(s,11) exten => sw-62-TORTURE,10,Goto(${torcont},s,begin) exten => sw-62-TORTURE,11,Goto(s,11) [std-priv-exten_61] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-63-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_61-63) exten => s,12,Return() exten => _sw-63-.,10,Voicemail(u${ext}) exten => _sw-63-.,11,Goto(s,11) exten => sw-63-,10,Goto(sw-63-.,10) exten => sw-63-NOANSWER,10,Voicemail(u${ext}) exten => sw-63-NOANSWER,11,Goto(s,11) exten => sw-63-ANSWER,10,Goto(s,11) exten => sw-63-BUSY,10,Voicemail(b${ext}) exten => sw-63-BUSY,11,Goto(s,11) exten => sw-63-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-63-DONTCALL,11,Goto(s,11) exten => sw-63-TORTURE,10,Goto(${torcont},s,begin) exten => sw-63-TORTURE,11,Goto(s,11) [std-priv-exten_62] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-64-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_62-64) exten => s,12,Return() exten => _sw-64-.,10,Voicemail(u${ext}) exten => _sw-64-.,11,Goto(s,11) exten => sw-64-,10,Goto(sw-64-.,10) exten => sw-64-NOANSWER,10,Voicemail(u${ext}) exten => sw-64-NOANSWER,11,Goto(s,11) exten => sw-64-ANSWER,10,Goto(s,11) exten => sw-64-BUSY,10,Voicemail(b${ext}) exten => sw-64-BUSY,11,Goto(s,11) exten => sw-64-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-64-DONTCALL,11,Goto(s,11) exten => sw-64-TORTURE,10,Goto(${torcont},s,begin) exten => sw-64-TORTURE,11,Goto(s,11) [std-priv-exten_63] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-65-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_63-65) exten => s,12,Return() exten => _sw-65-.,10,Voicemail(u${ext}) exten => _sw-65-.,11,Goto(s,11) exten => sw-65-,10,Goto(sw-65-.,10) exten => sw-65-NOANSWER,10,Voicemail(u${ext}) exten => sw-65-NOANSWER,11,Goto(s,11) exten => sw-65-ANSWER,10,Goto(s,11) exten => sw-65-BUSY,10,Voicemail(b${ext}) exten => sw-65-BUSY,11,Goto(s,11) exten => sw-65-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-65-DONTCALL,11,Goto(s,11) exten => sw-65-TORTURE,10,Goto(${torcont},s,begin) exten => sw-65-TORTURE,11,Goto(s,11) [std-priv-exten_64] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-66-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_64-66) exten => s,12,Return() exten => _sw-66-.,10,Voicemail(u${ext}) exten => _sw-66-.,11,Goto(s,11) exten => sw-66-,10,Goto(sw-66-.,10) exten => sw-66-NOANSWER,10,Voicemail(u${ext}) exten => sw-66-NOANSWER,11,Goto(s,11) exten => sw-66-ANSWER,10,Goto(s,11) exten => sw-66-BUSY,10,Voicemail(b${ext}) exten => sw-66-BUSY,11,Goto(s,11) exten => sw-66-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-66-DONTCALL,11,Goto(s,11) exten => sw-66-TORTURE,10,Goto(${torcont},s,begin) exten => sw-66-TORTURE,11,Goto(s,11) [std-priv-exten_65] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-67-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_65-67) exten => s,12,Return() exten => _sw-67-.,10,Voicemail(u${ext}) exten => _sw-67-.,11,Goto(s,11) exten => sw-67-,10,Goto(sw-67-.,10) exten => sw-67-NOANSWER,10,Voicemail(u${ext}) exten => sw-67-NOANSWER,11,Goto(s,11) exten => sw-67-ANSWER,10,Goto(s,11) exten => sw-67-BUSY,10,Voicemail(b${ext}) exten => sw-67-BUSY,11,Goto(s,11) exten => sw-67-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-67-DONTCALL,11,Goto(s,11) exten => sw-67-TORTURE,10,Goto(${torcont},s,begin) exten => sw-67-TORTURE,11,Goto(s,11) [std-priv-exten_66] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-68-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_66-68) exten => s,12,Return() exten => _sw-68-.,10,Voicemail(u${ext}) exten => _sw-68-.,11,Goto(s,11) exten => sw-68-,10,Goto(sw-68-.,10) exten => sw-68-NOANSWER,10,Voicemail(u${ext}) exten => sw-68-NOANSWER,11,Goto(s,11) exten => sw-68-ANSWER,10,Goto(s,11) exten => sw-68-BUSY,10,Voicemail(b${ext}) exten => sw-68-BUSY,11,Goto(s,11) exten => sw-68-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-68-DONTCALL,11,Goto(s,11) exten => sw-68-TORTURE,10,Goto(${torcont},s,begin) exten => sw-68-TORTURE,11,Goto(s,11) [std-priv-exten_67] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-69-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_67-69) exten => s,12,Return() exten => _sw-69-.,10,Voicemail(u${ext}) exten => _sw-69-.,11,Goto(s,11) exten => sw-69-,10,Goto(sw-69-.,10) exten => sw-69-NOANSWER,10,Voicemail(u${ext}) exten => sw-69-NOANSWER,11,Goto(s,11) exten => sw-69-ANSWER,10,Goto(s,11) exten => sw-69-BUSY,10,Voicemail(b${ext}) exten => sw-69-BUSY,11,Goto(s,11) exten => sw-69-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-69-DONTCALL,11,Goto(s,11) exten => sw-69-TORTURE,10,Goto(${torcont},s,begin) exten => sw-69-TORTURE,11,Goto(s,11) [std-priv-exten_68] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-70-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_68-70) exten => s,12,Return() exten => _sw-70-.,10,Voicemail(u${ext}) exten => _sw-70-.,11,Goto(s,11) exten => sw-70-,10,Goto(sw-70-.,10) exten => sw-70-NOANSWER,10,Voicemail(u${ext}) exten => sw-70-NOANSWER,11,Goto(s,11) exten => sw-70-ANSWER,10,Goto(s,11) exten => sw-70-BUSY,10,Voicemail(b${ext}) exten => sw-70-BUSY,11,Goto(s,11) exten => sw-70-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-70-DONTCALL,11,Goto(s,11) exten => sw-70-TORTURE,10,Goto(${torcont},s,begin) exten => sw-70-TORTURE,11,Goto(s,11) [std-priv-exten_69] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-71-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_69-71) exten => s,12,Return() exten => _sw-71-.,10,Voicemail(u${ext}) exten => _sw-71-.,11,Goto(s,11) exten => sw-71-,10,Goto(sw-71-.,10) exten => sw-71-NOANSWER,10,Voicemail(u${ext}) exten => sw-71-NOANSWER,11,Goto(s,11) exten => sw-71-ANSWER,10,Goto(s,11) exten => sw-71-BUSY,10,Voicemail(b${ext}) exten => sw-71-BUSY,11,Goto(s,11) exten => sw-71-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-71-DONTCALL,11,Goto(s,11) exten => sw-71-TORTURE,10,Goto(${torcont},s,begin) exten => sw-71-TORTURE,11,Goto(s,11) [std-priv-exten_70] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-72-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_70-72) exten => s,12,Return() exten => _sw-72-.,10,Voicemail(u${ext}) exten => _sw-72-.,11,Goto(s,11) exten => sw-72-,10,Goto(sw-72-.,10) exten => sw-72-NOANSWER,10,Voicemail(u${ext}) exten => sw-72-NOANSWER,11,Goto(s,11) exten => sw-72-ANSWER,10,Goto(s,11) exten => sw-72-BUSY,10,Voicemail(b${ext}) exten => sw-72-BUSY,11,Goto(s,11) exten => sw-72-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-72-DONTCALL,11,Goto(s,11) exten => sw-72-TORTURE,10,Goto(${torcont},s,begin) exten => sw-72-TORTURE,11,Goto(s,11) [std-priv-exten_71] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-73-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_71-73) exten => s,12,Return() exten => _sw-73-.,10,Voicemail(u${ext}) exten => _sw-73-.,11,Goto(s,11) exten => sw-73-,10,Goto(sw-73-.,10) exten => sw-73-NOANSWER,10,Voicemail(u${ext}) exten => sw-73-NOANSWER,11,Goto(s,11) exten => sw-73-ANSWER,10,Goto(s,11) exten => sw-73-BUSY,10,Voicemail(b${ext}) exten => sw-73-BUSY,11,Goto(s,11) exten => sw-73-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-73-DONTCALL,11,Goto(s,11) exten => sw-73-TORTURE,10,Goto(${torcont},s,begin) exten => sw-73-TORTURE,11,Goto(s,11) [std-priv-exten_72] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-74-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_72-74) exten => s,12,Return() exten => _sw-74-.,10,Voicemail(u${ext}) exten => _sw-74-.,11,Goto(s,11) exten => sw-74-,10,Goto(sw-74-.,10) exten => sw-74-NOANSWER,10,Voicemail(u${ext}) exten => sw-74-NOANSWER,11,Goto(s,11) exten => sw-74-ANSWER,10,Goto(s,11) exten => sw-74-BUSY,10,Voicemail(b${ext}) exten => sw-74-BUSY,11,Goto(s,11) exten => sw-74-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-74-DONTCALL,11,Goto(s,11) exten => sw-74-TORTURE,10,Goto(${torcont},s,begin) exten => sw-74-TORTURE,11,Goto(s,11) [std-priv-exten_73] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-75-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten_73-75) exten => s,12,Return() exten => _sw-75-.,10,Voicemail(u${ext}) exten => _sw-75-.,11,Goto(s,11) exten => sw-75-,10,Goto(sw-75-.,10) exten => sw-75-NOANSWER,10,Voicemail(u${ext}) exten => sw-75-NOANSWER,11,Goto(s,11) exten => sw-75-ANSWER,10,Goto(s,11) exten => sw-75-BUSY,10,Voicemail(b${ext}) exten => sw-75-BUSY,11,Goto(s,11) exten => sw-75-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-75-DONTCALL,11,Goto(s,11) exten => sw-75-TORTURE,10,Goto(${torcont},s,begin) exten => sw-75-TORTURE,11,Goto(s,11) [std-priv-exten] exten => s,1,Set(LOCAL(dev)=${ARG1}) exten => s,2,Set(LOCAL(ext)=${ARG2}) exten => s,3,Set(LOCAL(timeout)=${ARG3}) exten => s,4,Set(LOCAL(opts)=${ARG4}) exten => s,5,Set(LOCAL(torcont)=${ARG5}) exten => s,6,Set(LOCAL(dontcont)=${ARG6}) exten => s,7,Set(~~EXTEN~~=${EXTEN}) exten => s,8,Dial(${dev},${timeout},${opts}) exten => s,9,NoOp(${DIALSTATUS} was chosen) exten => s,10,Goto(sw-76-${DIALSTATUS},10) exten => s,11,NoOp(Finish switch-std-priv-exten-76) exten => s,12,Return() exten => _sw-76-.,10,Voicemail(u${ext}) exten => _sw-76-.,11,Goto(s,11) exten => sw-76-,10,Goto(sw-76-.,10) exten => sw-76-NOANSWER,10,Voicemail(u${ext}) exten => sw-76-NOANSWER,11,Goto(s,11) exten => sw-76-ANSWER,10,Goto(s,11) exten => sw-76-BUSY,10,Voicemail(b${ext}) exten => sw-76-BUSY,11,Goto(s,11) exten => sw-76-DONTCALL,10,Goto(${dontcont},s,begin) exten => sw-76-DONTCALL,11,Goto(s,11) exten => sw-76-TORTURE,10,Goto(${torcont},s,begin) exten => sw-76-TORTURE,11,Goto(s,11) [fillcidname] exten => s,1,GotoIf($["${CALLERID(num)}" = "" ]?2:3) exten => s,2,Return() exten => s,3,NoOp(Finish if-fillcidname-77) exten => s,4,Set(cidn=${DB(cidname/${CALLERID(num)})}) exten => s,5,GotoIf($["${CALLERID(name)}" != "" ]?6:9) exten => s,6,GotoIf($[("${cidn}" = "Privacy Manager" & "${CALLERID(name)}" != "Privacy Manager") | "${cidn}" = "" ]?7:8) exten => s,7,Set(DB(cidname/${CALLERID(num)})=${CALLERID(name)}) exten => s,8,NoOp(Finish if-if-fillcidname-78-79) exten => s,9,NoOp(Finish if-fillcidname-78) exten => s,10,GotoIf($[( "${cidn}" != "" ) & ( "${CALLERID(name)}" = "" | "${CALLERID(name)}" = "CODY,WY " | "${CALLERID(name)}" = "POWELL,WY " | "${CALLERID(name)}" = "WIRELESS CALLER" | "${CALLERID(name)}" = "SUBSCRIBER,WIRE" | "${CALLERID(name)}" = "CELLULAR ONE" | "${CALLERID(name)}" = "Cellular One Customer" | "${CALLERID(name)}" = "CELLULAR ONE " | "${CALLERID(name)}" = "Privacy Manager" | "${CALLERID(name)}" = "RIVERTON,WY " | "${CALLERID(name)}" = "BASIN,WY " | "${CALLERID(name)}" = "BILLINGS,MT " | "${CALLERID(name)}" = "PROVO,UT " | "${CALLERID(name)}" = "TOLL FREE " ) ]?11:12) exten => s,11,Set(CALLERID(name)=${cidn}) exten => s,12,NoOp(Finish if-fillcidname-80) exten => s,13,Return() [ciddial] exten => s,1,Set(LOCAL(dialnum)=${ARG1}) exten => s,2,Set(LOCAL(lookup)=${ARG2}) exten => s,3,Set(LOCAL(waittime)=${ARG3}) exten => s,4,Set(LOCAL(dialopts)=${ARG4}) exten => s,5,Set(LOCAL(ddev)=${ARG5}) exten => s,6,Set(cidnu=${CALLERID(num)}) exten => s,7,Set(cidn=${DB(cidname/${lookup})}) exten => s,8,Set(CALLERID(name)=${cidn}) exten => s,9,Dial(${ddev}/${dialnum}|${waittime}|${dialopts}) exten => s,10,GotoIf($["${DIALSTATUS}" = "CHANUNAVAIL" ]?11:19) exten => s,11,BackGround(try_voip) exten => s,12,Set(CALLERID(num)=$[7075679201]) exten => s,13,Dial(SIP/1${lookup}@tctwest,${waittime},${dialopts}) exten => s,14,GotoIf($["${DIALSTATUS}" = "CHANUNAVAIL" ]?15:18) exten => s,15,BackGround(try_cell) exten => s,16,Set(CALLERID(num)=$[${cidnu}]) exten => s,17,Dial(Zap/2/${lookup},${waittime},${dialopts}) exten => s,18,NoOp(Finish if-if-ciddial-81-82) exten => s,19,NoOp(Finish if-ciddial-81) exten => s,20,Return() [ciddial3] exten => s,1,Set(LOCAL(dialnum)=${ARG1}) exten => s,2,Set(LOCAL(lookup)=${ARG2}) exten => s,3,Set(LOCAL(waittime)=${ARG3}) exten => s,4,Set(LOCAL(dialopts)=${ARG4}) exten => s,5,Set(LOCAL(ddev)=${ARG5}) exten => s,6,Set(cidnu=${CALLERID(num)}) exten => s,7,Set(cidn=${DB(cidname/${lookup})}) exten => s,8,Set(CALLERID(name)=${cidn}) exten => s,9,Dial(${ddev}/${dialnum}|${waittime}|${dialopts}) exten => s,10,GotoIf($["${DIALSTATUS}" = "CHANUNAVAIL" ]?11:13) exten => s,11,BackGround(try_cell) exten => s,12,Dial(Zap/2/${lookup},${waittime},${dialopts}) exten => s,13,NoOp(Finish if-ciddial3-83) exten => s,14,Return() [ciddial2] exten => s,1,Set(LOCAL(dialnum)=${ARG1}) exten => s,2,Set(LOCAL(lookup)=${ARG2}) exten => s,3,Set(LOCAL(waittime)=${ARG3}) exten => s,4,Set(LOCAL(dialopts)=${ARG4}) exten => s,5,Set(LOCAL(ddev)=${ARG5}) exten => s,6,Set(cidn=${DB(cidname/${lookup})}) exten => s,7,Set(cidnu=${CALLERID(num)}) exten => s,8,Set(CALLERID(name)=${cidn}) exten => s,9,Set(CALLERID(num)=7075679201) exten => s,10,Dial(SIP/1${lookup}@tctwest,${waittime},${dialopts}) exten => s,11,GotoIf($["${DIALSTATUS}" = "CHANUNAVAIL" ]?12:19) exten => s,12,Set(CALLERID(num)=${cidnu}) exten => s,13,BackGround(try_zap) exten => s,14,Dial(${ddev}/${dialnum},${waittime}|${dialopts}) exten => s,15,GotoIf($["${DIALSTATUS}" = "CHANUNAVAIL" ]?16:18) exten => s,16,BackGround(try_cell) exten => s,17,Dial(Zap/2/${lookup},${waittime},${dialopts}) exten => s,18,NoOp(Finish if-if-ciddial2-84-85) exten => s,19,NoOp(Finish if-ciddial2-84) exten => s,20,Return() [callerid-liar] exten => s,1,TrySystem(/usr/bin/play /var/lib/asterisk/sounds/priv-callerintros/LIAR.gsm&) exten => s,2,Background(priv-liar) exten => s,3,Hangup() exten => s,4,Return() [callerid-bad] exten => s,1,Set(mycid=$[${CALLERID(num)}:"1([0-9]+)"]) exten => s,2,Set(CALLERID(num)=${mycid}) exten => s,3,Wait(0) exten => s,4,Return() [privacyManagerFailed] exten => s,1(begin),Background(PrivManInstructions) exten => s,2,PrivacyManager() exten => s,3,GotoIf($["${PRIVACYMGRSTATUS}" = "FAILED" ]?4:11) exten => s,4,Background(tt-allbusy) exten => s,5,Background(tt-somethingwrong) exten => s,6,Background(tt-monkeysintro) exten => s,7,Background(tt-monkeys) exten => s,8,Background(tt-weasels) exten => s,9,Hangup() exten => s,10,Goto(12) exten => s,11,Goto(homeline,s,postPriv) exten => s,12,NoOp(Finish if-privacyManagerFailed-86) [homeline] exten => s,1,Set(~~EXTEN~~=${EXTEN}) exten => s,2(begin),Answer() exten => s,3,Set(repeatcount=0) exten => s,4,Zapateller(nocallerid) exten => s,5,PrivacyManager() exten => s,6,GotoIf($["${PRIVACYMGRSTATUS}" = "FAILED" ]?7:11) exten => s,7,TrySystem(/usr/bin/play /var/lib/asterisk/sounds/privmanfailed.gsm) exten => s,8,Gosub(std-priv-exten,s,1(Zap/3r1&Zap/5r1,2,25,mtw,telemarket,telemarket)) exten => s,9,Hangup() exten => s,10,Return() exten => s,11,NoOp(Finish if-homeline-87) exten => s,12(postPriv),Gosub(fillcidname,s,1) exten => s,13,Set(CONFCIDNA=${CALLERID(name)}) exten => s,14,Set(CONFCIDNU=${CALLERID(num)}) exten => s,15,AGI(callall) exten => s,16,AGI(submit-announce.agi) exten => s,17,GotoIf($["${CALLERID(num)}" : "1" ]?18:19) exten => s,18,Gosub(callerid-bad,s,1) exten => s,19,NoOp(Finish if-homeline-88) exten => s,20,GotoIf($["${CALLERID(num)}" = "7077577685" & "${CALLERID(name)}" : "Privacy Manager" ]?21:22) exten => s,21,Gosub(callerid-liar,s,1) exten => s,22,NoOp(Finish if-homeline-89) exten => s,23,TrySystem(/usr/local/bin/who-is-it ${CALLERID(num)} "${CALLERID(name)}"&) exten => s,24,Set(lds=${DB(playlds/${CALLERID(num)})}) exten => s,25,GotoIf($["${lds}" = "1" ]?26:27) exten => s,26,SetMusicOnHold(mohlds) exten => s,27,NoOp(Finish if-homeline-90) exten => s,28,Set(direct=$[${DB(DirectCall/${CALLERID(num)})}]) exten => s,29,GotoIf($["${direct}" != "" & ${direct} != 0 ]?30:37) exten => s,30,verbose(direct is XXX#${direct}XXXX) exten => s,31,Playback(greetings/direct) exten => s,32,Playback(/var/spool/asterisk/voicemail/default/${direct}/greet) exten => s,33,TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm) exten => s,34,TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/${direct}/greet.wav&) exten => s,35,Goto(sw-92-${direct},10) exten => s,36,NoOp(Finish switch-if-homeline-91-92) exten => s,37,NoOp(Finish if-homeline-91) exten => s,38(loopback),GotoIfTime(*,*,20-25,dec?40) exten => s,39,Goto(42) exten => s,40,Playback(greetings/christmas) exten => s,41,Goto(103) exten => s,42,GotoIfTime(*,*,31,dec?44) exten => s,43,Goto(46) exten => s,44,Playback(greetings/newyear) exten => s,45,Goto(102) exten => s,46,GotoIfTime(*,*,1,jan?48) exten => s,47,Goto(50) exten => s,48,Playback(greetings/newyear) exten => s,49,Goto(101) exten => s,50,GotoIfTime(*,*,14,feb?52) exten => s,51,Goto(54) exten => s,52,Playback(greetings/valentines) exten => s,53,Goto(100) exten => s,54,GotoIfTime(*,*,17,mar?56) exten => s,55,Goto(58) exten => s,56,Playback(greetings/stPat) exten => s,57,Goto(99) exten => s,58,GotoIfTime(*,*,31,oct?60) exten => s,59,Goto(62) exten => s,60,Playback(greetings/halloween) exten => s,61,Goto(98) exten => s,62,GotoIfTime(*,mon,15-21,jan?64) exten => s,63,Goto(66) exten => s,64,Playback(greetings/mlkDay) exten => s,65,Goto(97) exten => s,66,GotoIfTime(*,thu,22-28,nov?68) exten => s,67,Goto(70) exten => s,68,Playback(greetings/thanksgiving) exten => s,69,Goto(96) exten => s,70,GotoIfTime(*,mon,25-31,may?72) exten => s,71,Goto(74) exten => s,72,Playback(greetings/memorial) exten => s,73,Goto(95) exten => s,74,GotoIfTime(*,mon,1-7,sep?76) exten => s,75,Goto(78) exten => s,76,Playback(greetings/labor) exten => s,77,Goto(94) exten => s,78,GotoIfTime(*,mon,15-21,feb?80) exten => s,79,Goto(82) exten => s,80,Playback(greetings/president) exten => s,81,Goto(93) exten => s,82,GotoIfTime(*,sun,8-14,may?84) exten => s,83,Goto(86) exten => s,84,Playback(greetings/mothers) exten => s,85,Goto(92) exten => s,86,GotoIfTime(*,sun,15-21,jun?88) exten => s,87,Goto(90) exten => s,88,Playback(greetings/fathers) exten => s,89,Goto(91) exten => s,90,Playback(greetings/hello) exten => s,91,NoOp(Finish iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-homeline-93-94-95-96-97-98-99-100-101-102-103-104-105) exten => s,92,NoOp(Finish iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-homeline-93-94-95-96-97-98-99-100-101-102-103-104) exten => s,93,NoOp(Finish iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-homeline-93-94-95-96-97-98-99-100-101-102-103) exten => s,94,NoOp(Finish iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-homeline-93-94-95-96-97-98-99-100-101-102) exten => s,95,NoOp(Finish iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-homeline-93-94-95-96-97-98-99-100-101) exten => s,96,NoOp(Finish iftime-iftime-iftime-iftime-iftime-iftime-iftime-iftime-homeline-93-94-95-96-97-98-99-100) exten => s,97,NoOp(Finish iftime-iftime-iftime-iftime-iftime-iftime-iftime-homeline-93-94-95-96-97-98-99) exten => s,98,NoOp(Finish iftime-iftime-iftime-iftime-iftime-iftime-homeline-93-94-95-96-97-98) exten => s,99,NoOp(Finish iftime-iftime-iftime-iftime-iftime-homeline-93-94-95-96-97) exten => s,100,NoOp(Finish iftime-iftime-iftime-iftime-homeline-93-94-95-96) exten => s,101,NoOp(Finish iftime-iftime-iftime-homeline-93-94-95) exten => s,102,NoOp(Finish iftime-iftime-homeline-93-94) exten => s,103,NoOp(Finish iftime-homeline-93) exten => s,104,Background(murphy-homeline-intro1) exten => _sw-92-.,10,Set(z=${direct}-2) exten => _sw-92-.,11,Goto(homeline-kids,${z},1) exten => sw-92-,10,Goto(sw-92-.,10) exten => sw-92-2,10,Gosub(std-priv-exten,s,1(Zap/3r1&Zap/5r1,2,25,mtw,telemarket,telemarket)) exten => sw-92-2,11,Goto(s,loopback) exten => sw-92-1,10,Gosub(std-priv-exten,s,1(Zap/6r3&Sip/murf,1,25,mpA(beep)tw,telemarket,telemarket)) exten => sw-92-1,11,Goto(s,loopback) exten => 1,1,TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm) exten => 1,2,TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/2/greet.wav&) exten => 1,3,Gosub(std-priv-exten,s,1(Zap/3r1&Zap/5r1,2,25,mtw,telemarket,telemarket)) exten => 1,4,Goto(s,loopback) exten => 2,1,Goto(homeline-kids,s,begin) exten => 21,1,Dial(IAX2/seaniax,20,T) exten => 3,1,Gosub(std-priv-exten,s,1(Zap/6r3&Sip/murf,1,25,mpA(beep)tw,telemarket,telemarket)) exten => 3,2,Goto(s,loopback) exten => 4,1,VoicemailMain() exten => 4,2,Goto(s,loopback) exten => 5,1,Goto(home-introduction,s,begin) exten => 6,1,Goto(telemarket,s,begin) exten => 7,1,agi(tts-riddle.agi) exten => 7,2,Background(gsm/what-time-it-is2) exten => 7,3,SayUnixTime() exten => 7,4,Goto(s,loopback) exten => 792,1,Goto(pageall,s,begin) exten => 793,1,Read(zz,,0,,1,0) exten => 793,2,SayDigits(${zz}) exten => t,1,Set(repeatcount=${repeatcount} + 1) exten => t,2,GotoIf($[${repeatcount} < 3 ]?3:4) exten => t,3,Goto(s,loopback) exten => t,4,NoOp(Finish if-homeline-106) exten => t,5,Hangup() exten => i,1,Background(invalid) exten => i,2,Goto(s,loopback) exten => o,1,Congestion() exten => fax,1,Dial(Zap/4) [pageall] exten => s,1(begin),AGI(callall) exten => s,2,MeetMe(5555,dtqp) exten => s,3,MeetMeAdmin(5555,K) exten => s,4,Hangup() exten => h,1(begin),MeetMeAdmin(5555,K) exten => h,2,Background(conf-muted) exten => h,3,Hangup() [add-to-conference] exten => start,1,NoCDR() exten => start,2,MeetMe(5555,dmqp) exten => h,1,Hangup() [home-introduction] exten => s,1(begin),Background(intro-options) exten => 1,1,Playback(priv-callerintros/${CALLERID(num)}) exten => 1,2,Goto(s,begin) exten => 2,1,Goto(home-introduction-record,s,begin) exten => 3,1,Goto(homeline,s,loopback) exten => 4,1,Playback(intro-intro) exten => 4,2,Goto(s,begin) exten => t,1,Goto(s,begin) exten => i,1,Background(invalid) exten => i,2,Goto(s,begin) exten => o,1,Goto(s,begin) [home-introduction-record] exten => s,1(begin),Background(intro-record-choices) exten => 1,1,Playback(intro-record) exten => 1,2,Goto(2,begin) exten => 2,1(begin),Background(intro-start) exten => 2,2,Background(beep) exten => 2,3,Record(priv-callerintros/${CALLERID(num)}:gsm,3) exten => 2,4,Background(priv-callerintros/${CALLERID(num)}) exten => 2,5,Goto(home-introduction,s,begin) exten => t,1,Goto(s,begin) exten => i,1,Background(invalid) exten => i,2,Goto(s,begin) exten => o,1,Goto(s,begin) [homeline-kids] exten => s,1(begin),Background(murphy-homeline-kids) exten => 1,1,TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm) exten => 1,2,TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/3/greet.wav&) exten => 1,3,Gosub(std-priv-exten,s,1(IAX2/seaniax&Zap/5r2,3,35,mtw,telemarket,telemarket)) exten => 1,4,Goto(homeline,s,loopback) exten => 2,1,TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm) exten => 2,2,TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/4/greet.wav&) exten => 2,3,Voicemail(u4) exten => 2,4,Goto(homeline,s,loopback) exten => 3,1,TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm) exten => 3,2,TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/5/greet.wav&) exten => 3,3,Gosub(std-priv-exten,s,1(Zap/3r2&Zap/5r2,5,35,mtw,telemarket,telemarket)) exten => 3,4,Goto(homeline,s,loopback) exten => 4,1,TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm) exten => 4,2,TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/6/greet.wav&) exten => 4,3,Gosub(std-priv-exten,s,1(Zap/3r2&Zap/5r2,6,35,mtw,telemarket,telemarket)) exten => 4,4,Goto(homeline,s,loopback) exten => 5,1,TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm) exten => 5,2,TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/7/greet.wav&) exten => 5,3,Gosub(std-priv-exten,s,1(Zap/3r2&Zap/5r2,7,35,mtw,telemarket,telemarket)) exten => 5,4,Goto(homeline,s,loopback) exten => 6,1,TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm) exten => 6,2,TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/8/greet.wav&) exten => 6,3,Gosub(std-priv-exten,s,1(Zap/3r2&Zap/5r2,8,35,mtw,telemarket,telemarket)) exten => 6,4,Goto(homeline,s,loopback) exten => 7,1,TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm) exten => 7,2,TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/9/greet.wav&) exten => 7,3,Gosub(std-priv-exten,s,1(Zap/3r2&Zap/5r2,9,35,mtw,telemarket,telemarket)) exten => 7,4,Goto(homeline,s,loopback) exten => t,1,Goto(s,begin) exten => i,1,Background(invalid) exten => i,2,Goto(s,begin) exten => o,1,Goto(s,begin) [voipworkline] exten => s,1(begin),Answer() exten => s,2,TrySystem(/usr/local/bin/who-is-it ${CALLERID(num)} "${CALLERID(name)}"&) exten => s,3,Goto(workline,s,loopback) exten => 7075679201,1,Answer() exten => 7075679201,2,TrySystem(/usr/local/bin/who-is-it ${CALLERID(num)} "${CALLERID(name)}"&) exten => 7075679201,3,Goto(workline,s,loopback) [workline] exten => s,1(begin),Answer() exten => s,2,Wait(1) exten => s,3,Set(repeatcount=0) exten => s,4,Zapateller(nocallerid) exten => s,5,Gosub(fillcidname,s,1) exten => s,6,TrySystem(/usr/local/bin/who-is-it ${CALLERID(num)} "${CALLERID(name)}"&) exten => s,7(loopback),Background(greetings/greeting) exten => s,8,Background(murphy-office-intro1) exten => 1,1,TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm) exten => 1,2,TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/1/greet.wav&) exten => 1,3,Gosub(std-priv-exten,s,1(Zap/6&Sip/murf,1,30,mtw,telemarket,telemarket)) exten => 1,4,Goto(s,loopback) exten => 4,1,VoicemailMain() exten => 4,2,Goto(s,loopback) exten => 6,1,Goto(telemarket,s,begin) exten => 793,1,Read(zz,,0,,1,0) exten => 793,2,SayDigits(${zz}) exten => t,1,Set(repeatcount=$[${repeatcount} + 1]) exten => t,2,GotoIf($[${repeatcount} < 3 ]?3:4) exten => t,3,Goto(s,loopback) exten => t,4,NoOp(Finish if-workline-107) exten => t,5,Hangup() exten => i,1,Background(invalid) exten => i,2,Goto(s,loopback) exten => o,1,Congestion() exten => fax,1,Answer() exten => fax,2,Dial(Zap/4) [dialFWD] ignorepat => 8 ignorepat => 9 exten => _83.,1,Set(CALLERID(name)=${FWDCIDNAME}) exten => _83.,2,Dial(IAX2/${FWDNUMBER}:${FWDPASSWORD}@iax2.fwdnet.net/${EXTEN:2},60,r) exten => _83.,3,Congestion() exten => _82NXX,1,Set(CALLERID(name)=${FWDCIDNAME}) exten => _82NXX,2,Dial(IAX2/${FWDNUMBER}:${FWDPASSWORD}@iax2.fwdnet.net/${EXTEN:2},60,r) exten => _82NXX,3,Congestion() exten => _92NXX,1,Set(CALLERID(name)=${FWDCIDNAME}) exten => _92NXX,2,Dial(IAX2/${FWDNUMBER}:${FWDPASSWORD}@iax2.fwdnet.net/${EXTEN:2},60,r) exten => _92NXX,3,Congestion() [dialiaxtel] ignorepat => 8 ignorepat => 9 exten => _81700NXXXXXX,1,Dial(IAX2/zorch:zilchnoodle@iaxtel.com/${EXTEN:1}@iaxtel) exten => _81800NXXXXXX,1,Dial(IAX2/zorch:zilchnoodle@iaxtel.com/${EXTEN:1}@iaxtel) exten => _91700NXXXXXX,1,Dial(IAX2/zorch:zilchnoodle@iaxtel.com/${EXTEN:1}@iaxtel) exten => _91800NXXXXXX,1,Dial(IAX2/zorch:zilchnoodle@iaxtel.com/${EXTEN:1}@iaxtel) [dialgoiax] ignorepat => 9 exten => _93.,1,Set(CALLERID(name)="Joe Worker") exten => _93.,2,Dial(IAX2/878201007658:stickyfinger295@server1.goiax.com/${EXTEN:2},60,r) exten => _93.,3,Congestion() [homefirst] ignorepat => 9 exten => _91NXXNXXXXXX,1,Gosub(ciddial,s,1(${EXTEN:1},${EXTEN:2},30,TW,Zap/1)) exten => _9754XXXX,1,Gosub(ciddial,s,1(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1)) exten => _9574XXXX,1,Gosub(ciddial,s,1(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1)) exten => _9202XXXX,1,Gosub(ciddial,s,1(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1)) exten => _9219XXXX,1,Gosub(ciddial,s,1(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1)) exten => _9254XXXX,1,Gosub(ciddial,s,1(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1)) exten => _9716XXXX,1,Gosub(ciddial,s,1(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1)) exten => _9NXXXXXX,1,Gosub(ciddial,s,1(1707${EXTEN:1},707${EXTEN:1},30,TW,Zap/1)) exten => _9011.,1,Gosub(ciddial,s,1(${EXTEN:1},${EXTEN:1},30,TW,Zap/1)) exten => _9911,1,Dial(Zap/1/911,30,T) exten => _9411,1,Dial(Zap/1/411,30,T) [workfirst] ignorepat => 9 exten => _91NXXNXXXXXX,1,Gosub(ciddial2,s,1(${EXTEN:1},${EXTEN:2},30,TW,Zap/1)) exten => _9754XXXX,1,Gosub(ciddial2,s,1(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1)) exten => _9574XXXX,1,Gosub(ciddial2,s,1(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1)) exten => _9202XXXX,1,Gosub(ciddial2,s,1(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1)) exten => _9219XXXX,1,Gosub(ciddial2,s,1(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1)) exten => _9254XXXX,1,Gosub(ciddial2,s,1(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1)) exten => _9716XXXX,1,Gosub(ciddial2,s,1(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1)) exten => _9NXXXXXX,1,Gosub(ciddial2,s,1(1707${EXTEN:1},707${EXTEN:1},30,TW,Zap/1)) exten => _9911,1,Dial(Zap/1/911,30,T) exten => _9411,1,Dial(Zap/1/411,30,T) [force_cell] ignorepat => 8 exten => _81NXXNXXXXXX,1,Gosub(ciddial,s,1(${EXTEN:1}#,${EXTEN:2},30,TW,Zap/2)) exten => _8754XXXX,1,Gosub(ciddial,s,1(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2)) exten => _8574XXXX,1,Gosub(ciddial,s,1(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2)) exten => _8202XXXX,1,Gosub(ciddial,s,1(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2)) exten => _8219XXXX,1,Gosub(ciddial,s,1(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2)) exten => _8254XXXX,1,Gosub(ciddial,s,1(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2)) exten => _8716XXXX,1,Gosub(ciddial,s,1(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2)) exten => _8NXXXXXX,1,Gosub(ciddial,s,1(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2)) exten => _8911,1,Dial(Zap/1/911|30|T) exten => _8411,1,Dial(Zap/1/411|30|T) [force_home] ignorepat => 8 exten => _81NXXNXXXXXX,1,Gosub(ciddial3,s,1(${EXTEN:1}#,${EXTEN:2},30,TW,Zap/1)) exten => _8754XXXX,1,Gosub(ciddial3,s,1(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1)) exten => _8574XXXX,1,Gosub(ciddial3,s,1(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1)) exten => _8202XXXX,1,Gosub(ciddial3,s,1(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1)) exten => _8219XXXX,1,Gosub(ciddial3,s,1(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1)) exten => _8254XXXX,1,Gosub(ciddial3,s,1(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1)) exten => _8716XXXX,1,Gosub(ciddial3,s,1(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1)) exten => _8NXXXXXX,1,Gosub(ciddial3,s,1(1707${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1)) exten => _8911,1,Dial(Zap/1/911|30|T) exten => _8411,1,Dial(Zap/1/411|30|T) [homeext] ignorepat => 8 ignorepat => 9 include => parkedcalls include => homefirst include => force_cell exten => s,1(loopback),Wait(0) exten => 1,1,Gosub(std-priv-exten,s,1(Zap/3&Zap/5,2,35,mtw,telemarket,telemarket)) exten => 1,2,Goto(s,loopback) exten => 2,1,Gosub(std-priv-exten,s,1(Zap/6&Zap/5,1,35,mpA(beep3)Tt,telemarket,telemarket)) exten => 2,2,Goto(s,loopback) exten => 4,1,VoicemailMain() exten => 5,1,Record(recording:gsm) exten => 5,2,Background(recording) exten => 6,1,Background(recording) exten => 760,1,DateTime() exten => 760,2,Goto(s,loopback) exten => 761,1,Record(announcement:gsm) exten => 761,2,TrySystem(/usr/bin/play /var/lib/asterisk/sounds/announcement.gsm&) exten => 761,3,Goto(s,loopback) exten => 762,1,agi(tts-riddle.agi) exten => 762,2,Background(gsm/what-time-it-is2) exten => 762,3,SayUnixTime() exten => 762,4,Goto(s,loopback) exten => 763,1,Set(CALLERID(num)=) exten => 763,2,Dial(Zap/6r3,35,mptA(beep3)) exten => 763,3,Hangup() exten => 764,1,Set(CALLERID(num)=) exten => 764,2,Dial(Zap/6r3,35,mptnA(beep3)) exten => 764,3,Hangup() exten => 765,1,Set(CALLERID(num)=) exten => 765,2,Dial(Zap/6r3,35,mptNA(beep3)) exten => 765,3,Hangup() exten => 766,1,Dial(Zap/6r3,35,mptNA(beep3)) exten => 766,2,Hangup() exten => 767,1,Dial(Zap/6r3,35,mptnA(beep3)) exten => 767,2,Hangup() exten => 769,1,Playtones(dial) exten => 769,2,Wait(2) exten => 769,3,Playtones(busy) exten => 769,4,Wait(2) exten => 769,5,Playtones(ring) exten => 769,6,Wait(2) exten => 769,7,Playtones(congestion) exten => 769,8,Wait(2) exten => 769,9,Playtones(callwaiting) exten => 769,10,Wait(2) exten => 769,11,Playtones(dialrecall) exten => 769,12,Wait(2) exten => 769,13,Playtones(record) exten => 769,14,Wait(2) exten => 769,15,Playtones(info) exten => 769,16,Wait(5) exten => 769,17,Hangup() exten => 790,1,MeetMe(790,p) exten => 792,1,Goto(pageall,s,begin) exten => 795,1,AGI(wakeup.agi) exten => 795,2,Congestion() exten => 544716,1,TrySystem(/usr/local/bin/who-is-it ${CALLERID(num)} "${CALLERID(name)}"&) exten => 544716,2,Goto(s,loopback) exten => i,1,Background(invalid) exten => i,2,Goto(s,loopback) exten => o,1,Goto(s,loopback) exten => t,1,Congestion() [fromvmhome] exten => 1,1,Dial(Zap/6&Sip/murf|20|Tt) exten => 2,1,Dial(Zap/3&Zap/5|20|Tt) exten => _707202XXXX,1,Gosub(ciddial,s,1(1${EXTEN:3},${EXTEN},30,TW,Zap/1)) exten => _707219XXXX,1,Gosub(ciddial,s,1(1${EXTEN:3},${EXTEN},30,TW,Zap/1)) exten => _707254XXXX,1,Gosub(ciddial,s,1(1${EXTEN:3},${EXTEN},30,TW,Zap/1)) exten => _707716XXXX,1,Gosub(ciddial,s,1(1${EXTEN:3},${EXTEN},30,TW,Zap/1)) exten => _707754XXXX,1,Gosub(ciddial,s,1(${EXTEN:3},${EXTEN},30,TW,Zap/1)) exten => _707574XXXX,1,Gosub(ciddial,s,1(${EXTEN:3},${EXTEN},30,TW,Zap/1)) exten => _NXXNXXXXXX,1,Gosub(ciddial,s,1(1${EXTEN},${EXTEN},30,TW,Zap/1)) exten => _1NXXNXXXXXX,1,Gosub(ciddial,s,1(${EXTEN},${EXTEN:1},30,TW,Zap/1)) exten => _754XXXX,1,Gosub(ciddial,s,1(${EXTEN},707${EXTEN},30,TW,Zap/1)) exten => _574XXXX,1,Gosub(ciddial,s,1(${EXTEN},707${EXTEN},30,TW,Zap/1)) exten => _NXXXXXX,1,Gosub(ciddial,s,1(1707${EXTEN},707${EXTEN},30,TW,Zap/1)) exten => _911,1,Gosub(ciddial,s,1(911,911,30,TW,Zap/1)) exten => _411,1,Gosub(ciddial,s,1(411,411,30,TW,Zap/1)) [fromvmwork] exten => 1,1,Dial(Zap/6&Sip/murf|20|Tt) exten => 2,1,Dial(Zap/3&Zap/5|20|Tt) exten => _707202XXXX,1,Gosub(ciddial,s,1(1${EXTEN:3},${EXTEN},30,TW,Zap/1)) exten => _707219XXXX,1,Gosub(ciddial,s,1(1${EXTEN:3},${EXTEN},30,TW,Zap/1)) exten => _707254XXXX,1,Gosub(ciddial,s,1(1${EXTEN:3},${EXTEN},30,TW,Zap/1)) exten => _707716XXXX,1,Gosub(ciddial,s,1(1${EXTEN:3},${EXTEN},30,TW,Zap/1)) exten => _707754XXXX,1,Gosub(ciddial,s,1(${EXTEN:3},${EXTEN},30,TW,Zap/1)) exten => _707574XXXX,1,Gosub(ciddial,s,1(${EXTEN:3},${EXTEN},30,TW,Zap/1)) exten => _NXXNXXXXXX,1,Gosub(ciddial,s,1(1${EXTEN},${EXTEN},30,TW,Zap/1)) exten => _1NXXNXXXXXX,1,Gosub(ciddial,s,1(${EXTEN},${EXTEN:1},30,TW,Zap/1)) exten => _754XXXX,1,Gosub(ciddial,s,1(${EXTEN},707${EXTEN},30,TW,Zap/1)) exten => _574XXXX,1,Gosub(ciddial,s,1(${EXTEN},707${EXTEN},30,TW,Zap/1)) exten => _NXXXXXX,1,Gosub(ciddial,s,1(1707${EXTEN},707${EXTEN},30,TW,Zap/1)) exten => 911,1,Gosub(ciddial,s,1(911,911,30,TW,Zap/1)) exten => 411,1,Gosub(ciddial,s,1(411,411,30,TW,Zap/1)) [fromSeanUniden] include => parkedcalls exten => 21,1,Dial(IAX2/seaniax,20,T) exten => _707202XXXX,1,Gosub(ciddial,s,1(${EXTEN:3},${EXTEN},30,TW,Zap/1)) exten => _707219XXXX,1,Gosub(ciddial,s,1(${EXTEN:3},${EXTEN},30,TW,Zap/1)) exten => _707254XXXX,1,Gosub(ciddial,s,1(${EXTEN:3},${EXTEN},30,TW,Zap/1)) exten => _707716XXXX,1,Gosub(ciddial,s,1(${EXTEN:3},${EXTEN},30,TW,Zap/1)) exten => _707754XXXX,1,Gosub(ciddial,s,1(${EXTEN:3},${EXTEN},30,TW,Zap/1)) exten => _707574XXXX,1,Gosub(ciddial,s,1(${EXTEN:3},${EXTEN},30,TW,Zap/1)) exten => _NXXNXXXXXX,1,Gosub(ciddial,s,1(1${EXTEN},${EXTEN},30,TW,Zap/1)) exten => _1NXXNXXXXXX,1,Gosub(ciddial,s,1(${EXTEN},${EXTEN:1},30,TW,Zap/1)) exten => _754XXXX,1,Gosub(ciddial,s,1(${EXTEN},707${EXTEN},30,TW,Zap/1)) exten => _574XXXX,1,Gosub(ciddial,s,1(${EXTEN},707${EXTEN},30,TW,Zap/1)) exten => _NXXXXXX,1,Gosub(ciddial,s,1(1707${EXTEN},707${EXTEN},30,TW,Zap/1)) exten => 911,1,Gosub(ciddial,s,1(911,911,30,TW,Zap/1)) exten => 411,1,Gosub(ciddial,s,1(411,411,30,TW,Zap/1)) [workext] ignorepat => 8 ignorepat => 9 include => parkedcalls include => workfirst include => force_home include => dialFWD include => dialiaxtel include => dialgoiax exten => s,1(loopback),Wait(0) exten => 1,1,Dial(Zap/3&Zap/5,20,tT) exten => 2,1,Dial(Zap/5&Zap/6,20,tT) exten => 21,1,Dial(IAX2/seaniax,20,T) exten => 22,1,Set(CALLERID(num)=1234567890) exten => 22,2,Set(CALLERID(name)=TestCaller) exten => 22,3,Dial(Zap/5,20,mP()A(beep)tw) exten => 22,4,NoOp(here is dialstatus: ${DIALSTATUS}...) exten => 22,5,Goto(s,loopback) exten => 4,1,VoicemailMain() exten => 4,2,Goto(s,loopback) exten => 5,1,Record(recording:gsm) exten => 5,2,Background(recording) exten => 6,1,ZapBarge() exten => 760,1,DateTime() exten => 760,2,Goto(s,loopback) exten => 761,1,ZapBarge() exten => 761,2,Goto(s,loopback) exten => 765,1,Playback(demo-echotest) exten => 765,2,Echo() exten => 765,3,Playback(demo-echodone) exten => 765,4,Goto(s,loopback) exten => 766,1,Festival(The other thing to watch is neuro-electronics: the ability to interface technology with our neural system: My wife: Sigrid: has had a cochlear implant since 1996. This once profoundly deaf person now uses the phone: recognizes accents: and listens to movies and recorded books.) exten => 766,2,Goto(s,loopback) exten => 767,1,agi(tts-riddle.agi) exten => 767,2,Background(gsm/what-time-it-is2) exten => 767,3,SayUnixTime() exten => 767,4,Goto(s,loopback) exten => 768,1,agi(tts-computer.agi) exten => 771,1,eagi(eagi-test) exten => 771,2,agi(my-agi-test) exten => 772,1,agi(wakeup.agi) exten => 775,1,GotoIf($[${EXTEN}=${EXTEN} ]?2:4) exten => 775,2,BackGround(digits/1) exten => 775,3,Goto(5) exten => 775,4,BackGround(digits/0) exten => 775,5,NoOp(Finish if-workext-108) exten => 775,6,GotoIf($[${EXTEN}=${LANGUAGE} ]?7:9) exten => 775,7,BackGround(digits/1) exten => 775,8,Goto(10) exten => 775,9,BackGround(digits/0) exten => 775,10,NoOp(Finish if-workext-109) exten => 775,11,BackGround(digits/2) exten => 776,1,Set(TEST=00359889811777) exten => 776,2,GotoIf($[${TEST}= 00359889811777 ]?3:5) exten => 776,3,BackGround(digits/1) exten => 776,4,Goto(6) exten => 776,5,BackGround(digits/0) exten => 776,6,NoOp(Finish if-workext-110) exten => 776,7,GotoIf($[${TEST}= 00359889811888 ]?8:10) exten => 776,8,BackGround(digits/1) exten => 776,9,Goto(11) exten => 776,10,BackGround(digits/0) exten => 776,11,NoOp(Finish if-workext-111) exten => 776,12,Hangup() exten => 790,1,MeetMe(790,p) exten => 792,1,Goto(pageall,s,begin) exten => 793,1,NoOp(Hello, this is included from include1.ael2) exten => 793,2,NoOp(This was included from include2.ael2) exten => 793,3,NoOp(This is include3.ael2!) exten => 793,4,NoOp(Include5.ael2 doesn't include anything, either!) exten => 793,5,NoOp(This is include4.ael2! Isn't it cool!?!?!?!) exten => 793,6,NoOp(4 doesn't include anything) exten => 795,1,AGI(wakeup.agi) exten => 795,2,Congestion() exten => 797,1,Set(CONFCIDNA=${CALLERID(name)}) exten => 797,2,Set(CONFCIDNU=${CALLERID(num)}) exten => 797,3,AGI(callall) exten => 797,4,AGI(submit-announce.agi) exten => 797,5,Hangup() [wakeup] exten => 3,1,Dial(Zap/3|30) exten => 4,1,Dial(Zap/4|30) exten => 5,1,Dial(Zap/5|30) exten => 6,1,Dial(Zap/6|30) exten => 99,1,Dial(IAX2/murfiaxphone|30) exten => 97,1,Dial(IAX2/ryaniax|30) exten => 94,1,Dial(IAX2/seaniax|30) [announce-all] exten => s,1(begin),MeetMe(5555,dtqp) exten => s,2,MeetMeAdmin(5555,K) exten => s,3,Hangup() exten => h,1,MeetMeAdmin(5555,K) exten => h,2,Hangup() [telemarket] exten => s,1(begin),Playback(telemarketer-intro) exten => s,2,Playback(telemarketer-choices) exten => 1,1,Goto(telemarket-charity,s,begin) exten => 2,1,Goto(telemarket-political,s,begin) exten => 3,1,Goto(telemarket-pollster,s,begin) exten => 4,1,Goto(telemarket-research,s,begin) exten => 5,1,Goto(telemarket-magazine,s,begin) exten => 6,1,Goto(telemarket-commercial,s,begin) exten => 7,1,Goto(telemarket-other,s,begin) exten => t,1,Goto(telemarket,s,begin) exten => i,1,Goto(telemarket,s,begin) exten => o,1,Goto(telemarket,s,begin) [telemarket-charity] exten => s,1(begin),Playback(telemark-charity-intro) exten => s,2,Playback(telemark-charity-choices) exten => 1,1,Goto(telemarket-char-disease,s,begin) exten => 2,1,Goto(telemarket-char-handicap,s,begin) exten => 3,1,Goto(telemarket-char-police,s,begin) exten => 4,1,Goto(telemarket-char-school,s,begin) exten => 5,1,Goto(telemarket-char-college,s,begin) exten => 6,1,Goto(telemarket-char-animal,s,begin) exten => 7,1,Goto(telemarket-char-candidate,s,begin) exten => 8,1,Goto(telemarket-char-abuse,s,begin) exten => 9,1,Goto(telemarket-char-other,s,begin) exten => t,1,Goto(telemarket,s,begin) exten => i,1,Goto(telemarket,s,begin) exten => o,1,Goto(telemarket,s,begin) [telemarket-char-disease] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-char-handicap] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-char-police] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-char-school] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-char-college] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-char-animal] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-char-candidate] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-char-abuse] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-char-other] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-sorry] exten => s,1(begin),Playback(telemarket-sorry) exten => s,2,Hangup() [telemarket-exception] exten => s,1(begin),Playback(telemarket-success) exten => s,2,Hangup() [telemarket-political] exten => s,1(begin),Playback(telemark-polit-intro) exten => s,2,Playback(telemark-polit-choices) exten => 1,1,Goto(telemarket-poli-Am1st,s,begin) exten => 2,1,Goto(telemarket-poli-American,s,begin) exten => 3,1,Goto(telemarket-poli-AmHer,s,begin) exten => 4,1,Goto(telemarket-poli-AmInd,s,begin) exten => 5,1,Goto(telemarket-poli-AmNaz,s,begin) exten => 6,1,Goto(telemarket-poli-Pot,s,begin) exten => 7,1,Goto(telemarket-poli-AmRef,s,begin) exten => 8,1,Goto(telemarket-poli-CFP,s,begin) exten => 9,1,Goto(telemarket-political2,s,begin) exten => t,1,Goto(telemarket,s,begin) exten => i,1,Goto(telemarket,s,begin) exten => o,1,Goto(telemarket,s,begin) [telemarket-political2] exten => s,1(begin),Playback(telemark-politx-intro) exten => s,2,Playback(telemark-polit2-choices) exten => 1,1,Goto(telemarket-poli-Communist,s,begin) exten => 2,1,Goto(telemarket-poli-Constit,s,begin) exten => 3,1,Goto(telemarket-poli-FamVal,s,begin) exten => 4,1,Goto(telemarket-poli-FreedSoc,s,begin) exten => 5,1,Goto(telemarket-poli-Grassroot,s,begin) exten => 6,1,Goto(telemarket-poli-Green,s,begin) exten => 7,1,Goto(telemarket-poli-Greens,s,begin) exten => 8,1,Goto(telemarket-poli-Independence,s,begin) exten => 9,1,Goto(telemarket-political3,s,begin) exten => t,1,Goto(telemarket,s,begin) exten => i,1,Goto(telemarket,s,begin) exten => o,1,Goto(telemarket,s,begin) [telemarket-political3] exten => s,1(begin),Playback(telemark-politx-intro) exten => s,2,Playback(telemark-polit3-choices) exten => 1,1,Goto(telemarket-poli-IndAm,s,begin) exten => 2,1,Goto(telemarket-poli-Labor,s,begin) exten => 3,1,Goto(telemarket-poli-Liber,s,begin) exten => 4,1,Goto(telemarket-poli-Light,s,begin) exten => 5,1,Goto(telemarket-poli-NatLaw,s,begin) exten => 6,1,Goto(telemarket-poli-New,s,begin) exten => 7,1,Goto(telemarket-poli-NewUn,s,begin) exten => 8,1,Goto(telemarket-poli-PeaceFree,s,begin) exten => 9,1,Goto(telemarket-political4,s,begin) exten => t,1,Goto(telemarket,s,begin) exten => i,1,Goto(telemarket,s,begin) exten => o,1,Goto(telemarket,s,begin) [telemarket-political4] exten => s,1(begin),Playback(telemark-politx-intro) exten => s,2,Playback(telemark-polit4-choices) exten => 1,1,Goto(telemarket-poli-Prohib,s,begin) exten => 2,1,Goto(telemarket-poli-Ref,s,begin) exten => 3,1,Goto(telemarket-poli-Revol,s,begin) exten => 4,1,Goto(telemarket-poli-SocPart,s,begin) exten => 5,1,Goto(telemarket-poli-SocAct,s,begin) exten => 6,1,Goto(telemarket-poli-SocEq,s,begin) exten => 7,1,Goto(telemarket-poli-SocLab,s,begin) exten => 8,1,Goto(telemarket-poli-SocWork,s,begin) exten => 9,1,Goto(telemarket-political5,s,begin) exten => t,1,Goto(telemarket,s,begin) exten => i,1,Goto(telemarket,s,begin) exten => o,1,Goto(telemarket,s,begin) [telemarket-political5] exten => s,1(begin),Playback(telemark-politx-intro) exten => s,2,Playback(telemark-polit5-choices) exten => 1,1,Goto(telemarket-poli-South,s,begin) exten => 2,1,Goto(telemarket-poli-SoInd,s,begin) exten => 3,1,Goto(telemarket-poli-USPac,s,begin) exten => 4,1,Goto(telemarket-poli-WTP,s,begin) exten => 5,1,Goto(telemarket-poli-WWP,s,begin) exten => 6,1,Goto(telemarket-poli-Democrat,s,begin) exten => 7,1,Goto(telemarket-poli-Repub,s,begin) exten => 8,1,Goto(telemarket-poli-other,s,begin) exten => t,1,Goto(telemarket,s,begin) exten => i,1,Goto(telemarket,s,begin) exten => o,1,Goto(telemarket,s,begin) [telemarket-poli-other] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-Repub] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-Democrat] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-WWP] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-WTP] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-USPac] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-SoInd] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-South] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-SocWork] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-SocLab] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-SocEq] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-SocAct] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-SocPart] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-Revol] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-Ref] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-Prohib] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-PeaceFree] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-NewUn] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-New] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-NatLaw] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-Light] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-Liber] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-Labor] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-IndAm] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-Independence] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-Greens] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-Green] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-Grassroot] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-FreedSoc] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-FamVal] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-Constit] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-Communist] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-CFP] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-AmRef] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-Pot] exten => s,1(begin),Goto(telemarket-political,s,begin) [telemarket-poli-AmNaz] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-AmInd] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-AmHer] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-American] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-poli-Am1st] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-pollster] exten => s,1(begin),Playback(telemark-poll-intro) exten => s,2,Goto(telemarket-sorry,s,begin) exten => t,1,Goto(telemarket,s,begin) exten => i,1,Goto(telemarket,s,begin) exten => o,1,Goto(telemarket,s,begin) [telemarket-research] exten => s,1(begin),Playback(telemark-research-intro) exten => s,2,Goto(telemarket-sorry,s,begin) exten => t,1,Goto(telemarket,s,begin) exten => i,1,Goto(telemarket,s,begin) exten => o,1,Goto(telemarket,s,begin) [telemarket-magazine] exten => s,1(begin),Playback(telemark-mag-choices) exten => 1,1,Goto(telemark-mag-new,s,begin) exten => 2,1,Goto(telemark-mag-renew,s,begin) exten => 3,1,Goto(telemark-mag-survey,s,begin) exten => 4,1,Goto(telemark-mag-verify,s,begin) exten => 5,1,Goto(telemark-mag-other,s,begin) exten => t,1,Goto(telemarket,s,begin) exten => i,1,Goto(telemarket,s,begin) exten => o,1,Goto(telemarket,s,begin) [telemark-mag-new] exten => s,1(begin),Playback(telemark-mag-new) exten => s,2,Hangup() exten => t,1,Goto(telemarket,s,begin) exten => i,1,Goto(telemarket,s,begin) exten => o,1,Goto(telemarket,s,begin) [telemark-mag-renew] exten => s,1(begin),Playback(telemark-mag-renew) exten => s,2,Hangup() exten => t,1,Goto(telemarket,s,begin) exten => i,1,Goto(telemarket,s,begin) exten => o,1,Goto(telemarket,s,begin) [telemark-mag-survey] exten => s,1(begin),Playback(telemark-mag-survey) exten => s,2,Hangup() exten => t,1,Goto(telemarket,s,begin) exten => i,1,Goto(telemarket,s,begin) exten => o,1,Goto(telemarket,s,begin) [telemark-mag-verify] exten => s,1(begin),Playback(telemark-mag-verify) exten => s,2,Hangup() exten => t,1,Goto(telemarket,s,begin) exten => i,1,Goto(telemarket,s,begin) exten => o,1,Goto(telemarket,s,begin) [telemark-mag-other] exten => s,1(begin),Goto(telemarket-sorry,s,begin) [telemarket-commercial] exten => s,1(begin),Playback(telemark-comm-intro) exten => s,2,Voicemail(u82) exten => s,3,Goto(telemarket-sorry,s,begin) exten => t,1,Goto(telemarket,s,begin) exten => i,1,Goto(telemarket,s,begin) exten => o,1,Goto(telemarket,s,begin) [telemarket-other] exten => s,1(begin),Playback(telemark-other-intro) exten => s,2,Hangup() exten => t,1,Goto(telemarket,s,begin) exten => i,1,Goto(telemarket,s,begin) exten => o,1,Goto(telemarket,s,begin) asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-test180000644000175000017500000000171111046713743020407 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:115 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:pbx_ael.c line:128 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:131 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:134 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:139 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:142 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. LOG: lev:4 file:ael2_parse line:518 func: main 1 contexts, 7 extensions, 28 priorities asterisk-1.6.1.0/pbx/ael/ael-test/ael-test20/0000755000175000017500000000000011175405517017702 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-test20/extensions.ael0000644000175000017500000000024410616370200022551 0ustar maniacmaniaccontext interesting { eswitches { Realtime/default@extensions; IAX2/context@${CURSERVER}; } 13 => NoOp(LuckyNumber!); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest10/0000755000175000017500000000000011175405520020051 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest10/extensions.ael0000644000175000017500000000423710465634503022747 0ustar maniacmaniacmacro endsess() { NoOp(hithere); } macro nullchk(type) { NoOp(${type} is this); } macro endcall(type) { switch(${type}) { case out: &nullchk(callid); if(${testnotnull}) { &endsess(); goto ptr1 ; // <-- goto call to valid label } else { ptr1: // <-- valid label Softhangup(${CHANNEL}); break ; } Noop(esac) ; } } macro endcall2(type) { switch(${type}) { case out: &nullchk(callid); if(${testnotnull}) { &endsess(); goto ptr1 ; // <-- goto call to valid label } case out2: { ptr1: // <-- valid label Softhangup(${CHANNEL}); break ; } Noop(esac) ; } } macro endcall3(type) { switch(${type}) { case out: &nullchk(callid); if(${testnotnull}) { &endsess(); goto ptr1 ; // <-- goto call to valid label } Noop(esac) ; } if(${testnotnull}) { goto ptr1; } switch(${type}) { case out: if(${testnotnull}) { ptr1: // <-- valid label Softhangup(${CHANNEL}); break ; } Noop(esac) ; } } macro endcall4(type) { switch(${type}) { case out: &nullchk(callid); if(${testnotnull}) { &endsess(); goto ptr1 ; // <-- goto call to valid label } Noop(esac) ; } if(${testnotnull}) { goto ptr1; } switch(${type}) { case out: switch(${type}) { case in: if(${testnotnull}) { ptr1: // <-- valid label Softhangup(${CHANNEL}); break ; } Noop(esac) ; } } } macro endcall5(type) { switch(${type}) { case out: &nullchk(callid); if(${testnotnull}) { &endsess(); goto ptr1 ; // <-- goto call to valid label } case in: &nullchk(callid); ptr2: if(${testnotnull}) { &endsess(); goto ptr1 ; // <-- goto call to valid label } Noop(esac) ; } if(${testnotnull}) { goto ptr1; } switch(${type}) { case out: switch(${type}) { case in: if(${testnotnull}) { ptr1: // <-- valid label Softhangup(${CHANNEL}); break ; } Noop(esac) ; } } } asterisk-1.6.1.0/pbx/ael/ael-test/ael-test5/0000755000175000017500000000000011175405520017617 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-test5/extensions.ael0000644000175000017500000004370010660336365022515 0ustar maniacmaniac/////////////////////////////////////////////////////////////////////////////// // Helpdesk Queue context hd-queue { s => { NoOp(Add a background sound to tell the user their options); Queue(helpdesk|t); NoOp(Put in options to apologize and send user to voicemail); }; 0 => goto default|0|1; 1 => { Dial(u41950@ixtlchochitl.zvbwu.edu); Congestion(10); Hangup; }; }; context l903-calling { _9903NXXXXXX => { Realtime(l903_ext,exchange,${EXTEN:4:3},l903_); if ("${l903_exchange}foo" = "foo") { Playback(num-outside-area); SayDigits(1); Playback(and-area-code); Playback(before-the-number); Hangup; }; &dialout(${EXTEN}); Congestion(10); Hangup; }; }; /////////////////////////////////////////////////////////////////////////////// // Extensions pulled from houston.conf // Converted the extension list to the database context houston-calling { _9713NXXXXXX => { Realtime(hou_713_ext,exchange,${EXTEN:4:3},hou_713_); if ("${hou_713_exchange}foo" = "foo") { Playback(num-outside-area); SayDigits(1); Playback(and-area-code); Playback(before-the-number); Hangup; }; &dialout(${EXTEN}); Congestion(10); Hangup; }; _9281NXXXXXX => { Realtime(hou_281_ext,exchange,${EXTEN:4:3},hou_281_); if ("${hou_281_exchange}foo" = "foo") { Playback(num-outside-area); SayDigits(1); Playback(and-area-code); Playback(before-the-number); Hangup; }; &dialout(${EXTEN}); Congestion(10); Hangup; }; _9832NXXXXXX => { Realtime(hou_832_ext,exchange,${EXTEN:4:3},hou_832_); if ("${hou_832_exchange}foo" = "foo") { Playback(num-outside-area); SayDigits(1); Playback(and-area-code); Playback(before-the-number); Hangup; }; &dialout(${EXTEN}); Congestion(10); Hangup; }; }; /////////////////////////////////////////////////////////////////////////////// // Extensions pulled from huntsville.conf // Converted the extension list to the database context huntsville-calling { _9NXXXXXX => { Realtime(hv_ext,exchange,${EXTEN:1:3},hv_); if ("${hv_exchange}foo" = "foo") { Playback(num-outside-area); SayDigits(1); Playback(and-area-code); Playback(before-the-number); Hangup; }; &dialout(${EXTEN}); Congestion(10); Hangup; }; _NXXXXXX => { NoOp(Stripping last four to see what extension we're dialing); Set(LAST4=${EXTEN:3}); StripLSD(4); }; i => Playback(pbx-invalid); h => Hangup; }; /////////////////////////////////////////////////////////////////////////////// // Extensions pulled from macros.conf macro dialout( number ) { Realtime(call_info,exten,${CALLERIDNUM:5},mon_); if ("${mon_monitor}" = "YES") { Dial(SIP/${number}@zgw1.zvbwu.edu,,wW); Dial(SIP/${number}@zgw2.zvbwu.edu,,wW); } else { Dial(SIP/${number}@zgw1.zvbwu.edu); Dial(SIP/${number}@zgw2.zvbwu.edu); }; return; }; // Standard extension macro: // ${ext} - Extension macro stdexten( ext ) { Realtime(sipusers,name,${ext},sip_user_); Realtime(call_info,exten|${ext},info_); if ("${sip_user_name}foo" = "foo") { Wait(1); &dialout(${ext}); Congestion(10); Hangup; }; NoOp(${CALLERIDNUM}); RealtimeUpdate(call_info,exten,${ext},calltrace,${CALLERIDNUM}); System(/usr/local/bin/db_update.sh call_info calltrace ${CALLERIDNUM} exten ${ext} &); &checkdnd(${ext}); &checkcf(${ext}); Realtime(call_info,exten,${CALLERIDNUM:5},mon_); if ("${mon_monitor}" = "YES") { Dial(SIP/${info_forwardto},25,wW); } else { Dial(SIP/${info_forwardto},25); }; switch ("${DIALSTATUS}") { case "BUSY": &checkcfb(${ext}); break; case "CHANUNAVAIL": Dial(IAX2/asterisk:password@ixtlchochitl.zvbwu.edu/${info_forwardto},25,wW); MailboxExists(${ext}); // if ("${VMBOXEXISTSSTATUS}" = "FAILED") { // Congestion(10); // Hangup; // }; &uvm(${ext}); Hangup; break; case "CONGESTION": MailboxExists(${ext}); if ("${VMBOXEXISTSSTATUS}" = "FAILED") { Congestion(10); Hangup; }; &bvm(${ext}); Hangup; break; default: MailboxExists(${ext}); if ("${VMBOXEXISTSSTATUS}" = "FAILED") { Congestion(10); Hangup; }; &uvm(${ext}); Hangup; }; Hangup; }; macro uvm( ext ) { Dial(SIP/u${ext}@ixtlchochitl.zvbwu.edu); Playback(im-sorry); Playback(voice-mail-system); Playback(down); Congestion(10); Hangup; }; macro bvm( ext ) { Dial(SIP/b${ext}@ixtlchochitl.zvbwu.edu); Playback(im-sorry); Playback(voice-mail-system); Playback(down); Congestion(10); Hangup; }; macro checkdnd( ext ) { if ("${info_donotdisturb}foo" = "foo") { NoOp(Do Not Disturb is not active); } else &uvm(${ext}); return; }; macro checkcf( ext ) { if ("${info_forwardto}foo" = "foo") if ("${ext}" = "43974") { Set(info_forwardto=${ext}&SCCP/${ext}); } else { Set(info_forwardto=${ext}&SIP/${ext}w); }; return; }; macro checkcfb( ext ) { if ("${info_forwardbusy}foo" = "foo") { Wait(1); MailboxExists(${ext}); if ("${VMBOXEXISTSSTATUS}" = "FAILED") { &dialout(${ext}); Hangup; }; &bvm(${ext}); Hangup; }; &stdexten(${info_forwardbusy}); return; }; /////////////////////////////////////////////////////////////////////////////// // Extensions pulled from test.conf context test-include { includes { test-digium; test-sounds; test-phinfo; }; }; context test-digium { *500 => { Dial(IAX2/guest@misery.digium.com/s@default); Playback(demo-nogo); Hangup; }; }; context test-sounds { *501 => { Answer; Musiconhold; Wait(1); Hangup; }; }; context test-phinfo { *505 => { Answer; NoOp(${CALLERIDNUM:5}); SayDigits(${CALLERIDNUM:5}); Hangup; }; }; /////////////////////////////////////////////////////////////////////////////// // Extensions pulled from external.conf context long-distance { includes { local1; }; _91XXXXXXXXXX => &dialout(${EXTEN}); _9011. => &dialout(${EXTEN}); }; context local1 { includes { default; }; 911 => &dialout(911); 9911 => &dialout(9911); _9NXXXXXX => goto huntsville-calling|${EXTEN}|1; _936NXXXXXX => { goto 9${EXTEN:3}|1; Congestion(10); Hangup; }; _832NXXXXXX => { goto 9${EXTEN}|1; Congestion(10); Hangup; }; _713NXXXXXX => { goto 9${EXTEN}|1 ; Congestion(10); Hangup; }; _281NXXXXXX => { goto 9${EXTEN}|1; Congestion(10); Hangup; }; _NXXNXXXXXX => { goto 9${EXTEN}|1; goto 91${EXTEN}|1; Congestion(10); Hangup; }; _91800NXXXXXX => &dialout(${EXTEN}); _91866NXXXXXX => &dialout(${EXTEN}); _91877NXXXXXX => &dialout(${EXTEN}); _91888NXXXXXX => &dialout(${EXTEN}); _91900NXXXXXX => &dialout(${EXTEN}); _91976NXXXXXX => &dialout(${EXTEN}); _9713NXXXXXX => goto houston-calling|${EXTEN}|1; _9281NXXXXXX => goto houston-calling|${EXTEN}|1; _9832NXXXXXX => goto houston-calling|${EXTEN}|1; _9903NXXXXXX => goto l903-calling|${EXTEN}|1; _31NXXNXXXXXX => &dialout(${EXTEN}); h => Hangup; }; /////////////////////////////////////////////////////////////////////////////// // Extensions pulled from internal.conf context from-scm2 { _4XXXX => { NoOp(DIALING SIP EXTENSION ${EXTEN} - FROM ${CALLERIDNUM}); Dial(SIP/${EXTEN},20,wW); Hangup; }; _6XXXX => { NoOp(DIALING SIP EXTENSION ${EXTEN} - FROM ${CALLERIDNUM}); Dial(SIP/${EXTEN},20,wW); Hangup; }; }; /////////////////////////////////////////////////////////// // All internal extensions work through the default context // Phones that can only make internal calls should be in // this context. /////////////////////////////////////////////////////////// context default { // Include the contexts in the files that allow us to make these phone calls includes { vm-include; apps-include; test-include; }; // ALWAYS have an 'h' extension h => { NoOp(Hangup cause was: ${HANGUPCAUSE}); Hangup; }; // We like to hear that we dialed an invalid extension i => Playback(pbx-invalid); // Dial the operator 0 => &dialout(0); // Send voicemail calls to the vm-* contexts to be handled voicemail => goto vm-direct|s|1; 5555 => goto vm-direct|s|1; 62100 => goto vm-extension|s|1; // These are our campus extensions, send them to the macro _6XXXX => &stdexten(${EXTEN}); _4XXXX => &stdexten(${EXTEN}); // These are campus extensions as well, might need to take this out though. _9294XXXX => goto _4XXXX|1; _9496XXXX => goto _6XXXX|1; // These allows us to dial from the directory in our phone without worrying about dialing 9 _936294XXXX => { goto ${EXTEN:5}|1; goto 9${EXTEN:3}|1; Congestion(10); Hangup; }; _936496XXXX => { goto ${EXTEN:5}|1; goto 9${EXTEN:3}|1; Congestion(10); Hangup; }; }; /////////////////////////////////////////////////////////////////////////////// // Extensions pulled from apps.conf context apps-include { includes { app-agents; app-dnd; app-callforward; app-calltrace; app-conferences; app-ssd; app-psd; app-idblock; app-helpdesk; app-dictate; app-set-monitor; }; }; context app-agents { *54 => { Answer; Wait(1); Read(agent_no|agent-user); AgentCallbackLogin(${agent_no}|s${CALLERIDNUM:5}); Playback(agent-loginok); Hangup; }; *55 => { Answer; Wait(1); AgentCallbackLogin(${agent_no}); Hangup; }; }; context app-calltrace { // caller dials this to find out the last call missed and possibly call back *69 => goto app-calltrace-perform|s|1; }; context app-calltrace-perform { s => { Answer; Wait(1); Background(info-about-last-call); Background(telephone-number); RealTime(call_info|exten|${CALLERIDNUM:5}|ct_); if ("${ct_calltrace}foo" = "foo") { Playback(loligo/from-unknown-caller); Hangup; } else { SayDigits("${ct_calltrace}"); Set(TIMEOUT(digit)=3); Set(TIMEOUT(response)=7); Background(loligo/to-call-this-number); Background(press-1); Background(loligo/silence/5); }; }; 1 => goto local1|${ct_calltrace}|1; i => { Playback(vm-goodbye); Hangup; }; t => { Playback(vm-goodbye); Hangup; }; }; context app-set-monitor { *50 => { Realtime(call_info,exten,${CALLERIDNUM:5},mon_set_); if ("${mon_set_monitor}" = "YES") { RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},monitor|); System(/usr/local/bin/db_update.sh call_info monitor '' exten ${CALLERIDNUM:5} &); } else { RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},monitor,YES); System(/usr/local/bin/db_update.sh call_info monitor YES exten ${CALLERIDNUM:5} &); }; NoOp(${mon_set_monitor}); Hangup; }; }; context app-dnd { *78 => { Answer; Wait(1); RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},donotdisturb,YES); System(/usr/local/bin/db_update.sh call_info donotdisturb YES exten ${CALLERIDNUM:5} &); Playback(do-not-disturb); Playback(loligo/activated); Hangup; }; *79 => { Answer; Wait(1); RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},donotdisturb|); System(/usr/local/bin/db_update.sh call_info donotdisturb '' exten ${CALLERIDNUM:5} &); Playback(do-not-disturb); Playback(loligo/de-activated); Hangup; }; }; context app-callforward { // forwards calling extension to input number *72{EXTEN} _*72. => { RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},forwardto,${EXTEN:3}); System(/usr/local/bin/db_update.sh call_info forwardto ${EXTEN:3} exten ${CALLERIDNUM:5} &); Answer; Wait(1); Playback(loligo/call-fwd-unconditional); Playback(loligo/for); Playback(loligo/extension); SayDigits(${CALLERIDNUM:5}); Playback(loligo/is-set-to); SayDigits(${EXTEN:3}); Hangup; }; // prompts for extension to forward to *72 => { Answer; Wait(1); Playback(please-enter-your); Playback(extension); Background(then-press-pound); VMAuthenticate(|s); Background(loligo/ent-target-attendant); Read(toext,loligo/then-press-pound); Wait(1); RealtimeUpdate(call_info,exten,${AUTH_MAILBOX},forwardto,${toext}); System(/usr/local/bin/db_update.sh call_info forwardto ${toext} exten ${AUTH_MAILBOX} &); Playback(loligo/call-fwd-unconditional); Playback(loligo/for); Playback(loligo/extension); SayDigits(${AUTH_MAILBOX}); Playback(loligo/is-set-to); SayDigits(${toext}); Hangup; }; // cancels dialed extension call forward _*73. => { Realtime(voicemail,mailbox,${EXTEN:3},auth_); Answer; Wait(1); Authenticate(${auth_password}); RealtimeUpdate(call_info,exten,${EXTEN:3},forwardto,); System(/usr/local/bin/db_update.sh call_info forwardto '' exten ${EXTEN:3} &); Wait(1); SayDigits(${EXTEN:3}); Playback(loligo/call-fwd-cancelled); Hangup; }; // cancels call forward for calling extension *73 => { RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},forwardto,); System(/usr/local/bin/db_update.sh call_info forwardto '' exten ${CALLERIDNUM:5} &); Answer; Wait(1); Playback(loligo/call-fwd-cancelled); Hangup; }; // dialed call forward on busy _*90. => { RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},forwardbusy,${EXTEN:3}); System(/usr/local/bin/db_update.sh call_info forwardbusy ${EXTEN:3} exten ${CALLERIDNUM:5} &); Answer; Wait(1); Playback(loligo/call-fwd-on-busy); Playback(loligo/for); Playback(loligo/extension); SayDigits(${CALLERIDNUM:5}); Playback(loligo/is-set-to); SayDigits(${EXTEN:3}); Hangup; }; // cancels call forward on busy for calling extension *91 => { RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},forwardbusy|); System(/usr/local/bin/db_update.sh call_info forwardbusy '' exten ${CALLERIDNUM:5} &); Answer; Wait(1); Playback(loligo/call-fwd-on-busy); Playback(loligo/de-activated); Hangup; }; h => Hangup; }; context app-idblock { _*67. => { Set(CALLERID(name)=Anonymous); &stdexten(${EXTEN:3}); }; }; context app-dictate { *1 => { Dictate(); Hangup; }; }; context app-ssd { // *59 - Set system speed dial to digits // *59 0 - Delete system speed dial // *59 - Review system speed dial // *1xx - Dial speed dial _*59XXX. => { Answer; RealtimeUpdate(ssd,sd,${EXTEN:3:2},extension,${EXTEN:5}); System(/usr/local/bin/db_update.sh systemsd extension ${EXTEN:5} sd ${EXTEN:3:2} &); Wait(1); Playback(loligo/speed-dial); SayDigits(${EXTEN:3:2}); Playback(loligo/has-been-set-to); SayDigits(${EXTEN:5}); Hangup; }; _*59XX0 => { Answer; RealtimeUpdate(ssd,sd,${EXTEN:3:2},extension,); System(/usr/local/bin/db_update.sh systemsd extension '' sd ${EXTEN:3:2} &); Wait(1); Playback(loligo/speed-dial); SayDigits(${EXTEN:3:2}); Playback(loligo/has-been-cleared); Hangup; }; _*59XX => { Answer; Realtime(ssd,sd,${EXTEN:3},ssd_); if ("${ssd_extension}foo" = "foo") { Playback(loligo/speed-dial); SayDigits(${EXTEN:3:2}); Playback(loligo/is-not-set); Hangup; }; Wait(1); Playback(loligo/speed-dial); SayDigits(${EXTEN:3:2}); Playback(loligo/is-set-to); SayDigits(${ssd_extension}); Hangup; }; // NTC = number to call _*1XX => { Realtime(ssd,sd,${EXTEN:2},ssd_); if ("${ssd_extension}foo" = "foo") { Answer; Wait(1); Playback(loligo/speed-dial); SayDigits(${EXTEN:2}); Playback(loligo/is-not-set); Hangup; }; &stdexten(${ssd_extension}); Congestion(10); Hangup; }; }; macro check-psd-exists ( ext ) { Realtime(psd,extension,${ext},psd_); if ("${psd_extension}foo" = "foo") { System(/usr/local/bin/create_psd.sh ${ext}); } else NoOp(PSD set for ${ext}); return; }; context app-psd { // *89 - Set personal speed dial to digits // *89 0 - Delete personal speed dial // *89 - Review personal speed dial // *2xx - Dial personal speed dial _*89XXX. => { &check-psd-exists(${CALLERIDNUM:5}); Answer; RealtimeUpdate(psd,extension,${CALLERIDNUM:5},s${EXTEN:3:2},${EXTEN:5}); System(/usr/local/bin/db_update.sh personalsd s${EXTEN:3:2} ${EXTEN:5} extension ${CALLERIDNUM:5} &); Wait(1); Playback(loligo/speed-dial); SayDigits(${EXTEN:3:2}); Playback(loligo/has-been-set-to); SayDigits(${EXTEN:5}); Hangup; }; _*89XX0 => { &check-psd-exists(${CALLERIDNUM:5}); Answer; RealtimeUpdate(psd|extension|${CALLERIDNUM:5}|s${EXTEN:3:2}|); System(/usr/local/bin/db_update.sh personalsd s${EXTEN:3:2} '' extension ${CALLERIDNUM:5} &); Wait(1); Playback(loligo/speed-dial); SayDigits(${EXTEN:3:2}); Playback(loligo/has-been-cleared); Hangup; }; _*89XX => { &check-psd-exists(${CALLERIDNUM:5}); Answer; Realtime(psd|extension|${CALLERIDNUM:5}|psd_); Wait(1); if ("${psd_s${EXTEN:3:2}}foo" = "foo") { Playback(loligo/speed-dial); SayDigits(${EXTEN:3:2}); Playback(loligo/is-not-set); Hangup; }; Playback(loligo/speed-dial); SayDigits(${EXTEN:3:2}); Playback(loligo/is-set-to); SayDigits(${psd_s${EXTEN:3:2}}); Hangup; }; // NTC = number to call _*2XX => { &check-psd-exists(${CALLERIDNUM:5}); Realtime(psd|extension|${CALLERIDNUM:5}|psd_); if ("${psd_s${EXTEN:2}}foo" = "foo") { Answer; Wait(1); Playback(loligo/speed-dial); SayDigits(${EXTEN:2}); Playback(loligo/is-not-set); Hangup; }; &stdexten(${psd_s${EXTEN:2}}); Congestion(10); Hangup; }; }; context app-helpdesk { *4357 => { &stdexten(41950); Congestion; }; }; context app-conferences { // waiting for room number announcement *86 => goto app-conf-hidden|s|1; }; context app-conf-hidden { s => { Wait(1); Playback(loligo/please-enter-the); Playback(loligo/extension); read(roomtoenter,loligo/then-press-pound); Meetme(${roomtoenter}); Waitexten(8); Hangup; }; _1. => Meetme(${EXTEN}); }; /////////////////////////////////////////////////////////////////////////////// // Extensions pulled from vm.conf: context vm-include { includes { vm-direct; vm-extension; vm-directory; }; }; context vm-direct { s => { Dial(SIP/5555@ixtlchochitl.zvbwu.edu,20); Playback(im-sorry); Playback(voice-mail-system); Playback(down); Playback(extra/pls-try-call-later); Congestion(10); Hangup; }; }; context vm-extension { s => { Dial(SIP/62100@ixtlchochitl.zvbwu.edu,20); Playback(im-sorry); Playback(voice-mail-system); Playback(down); Playback(extra/pls-try-call-later); Congestion(10); Hangup; }; }; context vm-directory { 5556 => { Dial(SIP/5556@ixtlchochitl.zvbwu.edu); Playback(im-sorry); Playback(voice-mail-system); Playback(down); Playback(extra/pls-try-call-later); Congestion(10); Hangup; }; }; asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-ntest90000644000175000017500000000404310723063404020477 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -n option if you aren't interested in seeing all the instructions generated by the compiler) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:113 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:pbx_ael.c line:126 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:129 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. Executed ast_context_find_or_create(conts, name=workext, registrar=pbx_ael); Executed ast_context_add_ignorepat2(con, value=8, registrar=pbx_ael); Executed ast_context_add_ignorepat2(con, value=9, registrar=pbx_ael); Executed ast_add_extension2(context=workext, rep=0, exten=793, priority=1, label=(null), callerid=(null), appl=Set, data=QUERYSTRING=SELECT\ foo\,\ bar\ FROM\ foobar, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=workext, rep=0, exten=793, priority=2, label=(null), callerid=(null), appl=Verbose, data=2|${QUERYSTRING}, FREE, registrar=pbx_ael); Executed ast_add_extension2(context=workext, rep=0, exten=793, priority=3, label=(null), callerid=(null), appl=Set, data=query=$["SELECT foo\, bar FROM foobar" ], FREE, registrar=pbx_ael); Executed ast_add_extension2(context=workext, rep=0, exten=793, priority=4, label=(null), callerid=(null), appl=Verbose, data=2|${query}, FREE, registrar=pbx_ael); LOG: lev:2 file:pbx_ael.c line:131 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. Executed ast_merge_contexts_and_delete(); LOG: lev:2 file:pbx_ael.c line:134 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. Executed ast_walk_contexts(); LOG: lev:2 file:pbx_ael.c line:137 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. LOG: lev:4 file:ael2_parse line:531 func: main 1 contexts, 1 extensions, 4 priorities asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-test200000644000175000017500000000171010723063404020370 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:113 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:pbx_ael.c line:126 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:129 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:131 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:134 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:137 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. LOG: lev:4 file:ael2_parse line:531 func: main 1 contexts, 1 extensions, 1 priorities asterisk-1.6.1.0/pbx/ael/ael-test/runtests0000755000175000017500000000241310466233565017643 0ustar maniacmaniac#!/bin/bash ORIG=`mktemp /tmp/mytest.XXXXXX` NEW=`mktemp /tmp/mytest.XXXXXX` do_filter() { sed 's/line:[0-9]*//; /^Executed.*/d; s/column=[0-9]*/ /; s/Cols: [0-9]*-[0-9]*/___/' } for i in ael-test*; do echo -n Test: $i.................. (cd $i; ../../../../utils/aelparse -n -d | grep -v -i 'seconds' > ../res.$i) do_filter < res.$i > $NEW do_filter < ref.$i > $ORIG if (diff -q $NEW $ORIG > /dev/null 2>&1 ) then echo PASSED rm res.$i else echo %%%%%%FAILED%%%%%% # diff -u ref.$i res.$i diff -u $ORIG $NEW fi done for i in ael-ntest*; do echo -n Test: $i................. (cd $i; ../../../../utils/aelparse -d | grep -v -i 'seconds' > ../res.$i) do_filter < res.$i > $NEW do_filter < ref.$i > $ORIG if (diff -q $NEW $ORIG > /dev/null 2>&1 ) then echo PASSED rm res.$i else echo %%%%%%FAILED%%%%%% # diff -u ref.$i res.$i diff -u $ORIG $NEW fi done for i in ael-vtest*; do echo -n Test: $i................. (cd $i; ../../../../utils/aelparse -d -w -n | grep -v -i 'seconds' > ../res2.$i) if (diff -q ref.$i $i/extensions.conf.aeldump > /dev/null 2>&1 ) then echo PASSED rm res2.$i rm $i/extensions.conf.aeldump else echo %%%%%%FAILED%%%%%% # diff -u ref.$i res.$i diff -u ref.$i $i/extensions.conf.aeldump fi done rm $NEW $ORIG asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-test60000644000175000017500000000572011060072241020313 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:115 func: pbx_load_module Starting AEL load process. LOG: lev:4 file:ael.flex line:437 func: ael_yylex File=./extensions.ael, line=165, column=49: Mismatched '}' in expression! LOG: lev:4 file:ael.y line:777 func: ael_yyerror ==== File: ./extensions.ael, Line 165, Cols: 52-52: Error: syntax error, unexpected '=', expecting ')' LOG: lev:4 file:ael.flex line:437 func: ael_yylex File=./extensions.ael, line=174, column=49: Mismatched '}' in expression! LOG: lev:4 file:ael.y line:777 func: ael_yyerror ==== File: ./extensions.ael, Line 174, Cols: 52-52: Error: syntax error, unexpected '=', expecting ')' LOG: lev:4 file:ael.flex line:437 func: ael_yylex File=./extensions.ael, line=222, column=41: Mismatched '}' in expression! LOG: lev:4 file:ael.y line:777 func: ael_yyerror ==== File: ./extensions.ael, Line 222, Cols: 44-44: Error: syntax error, unexpected '=', expecting ')' LOG: lev:4 file:ael.y line:777 func: ael_yyerror ==== File: ./extensions.ael, Line 291, Cols: 22-33: Error: syntax error, unexpected word, expecting '(' or ';' or '=' or ':' LOG: lev:2 file:pbx_ael.c line:128 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:3 file:pval.c line:672 func: check_macro_returns Warning: file ./extensions.ael, line 116-125: The macro dialout does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:672 func: check_macro_returns Warning: file ./extensions.ael, line 129-182: The macro stdexten does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:672 func: check_macro_returns Warning: file ./extensions.ael, line 184-191: The macro uvm does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:672 func: check_macro_returns Warning: file ./extensions.ael, line 193-200: The macro bvm does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:672 func: check_macro_returns Warning: file ./extensions.ael, line 202-207: The macro checkdnd does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:672 func: check_macro_returns Warning: file ./extensions.ael, line 209-216: The macro checkcf does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:672 func: check_macro_returns Warning: file ./extensions.ael, line 218-230: The macro checkcfb does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:672 func: check_macro_returns Warning: file ./extensions.ael, line 688-694: The macro check-psd-exists does not end with a return; I will insert one. LOG: lev:4 file:pbx_ael.c line:144 func: pbx_load_module Sorry, but 4 syntax errors and 0 semantic errors were detected. It doesn't make sense to compile. LOG: lev:4 file:ael2_parse line:520 func: main 0 contexts, 0 extensions, 0 priorities asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-test20000644000175000017500000001100310723063404020304 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:113 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:ael.flex line:662 func: setup_filestack --Read in included file ././apptest.ael2, 3474 chars LOG: lev:3 file:ael.y line:546 func: ael_yyparse ==== File: ././apptest.ael2, Line 46, Cols: 8-11: Suggestion: Use the goto statement instead of the Goto() application call in AEL. LOG: lev:2 file:pbx_ael.c line:126 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 35-35: application call to EndWhile affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 37-37: application call to ExecIf affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 38-38: application call to ExecIfTime affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 44-44: application call to Gosub affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 45-45: application call to GosubIf affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:1346 func: check_goto Warning: file ././apptest.ael2, line 46-46: goto: Couldn't find goto target cont|exten|prior, not even in extensions.conf! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 47-47: application call to GotoIf affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 48-48: application call to GotoIfTime affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 58-58: application call to Macro affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2512 func: check_pval_item Warning: file ././apptest.ael2, line 59-59: I am converting the MacroExit call here to a return statement. LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 60-60: application call to MacroIf affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 85-85: application call to Random affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 94-94: application call to Return affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 119-119: application call to StackPop affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 141-141: application call to While affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:2 file:pbx_ael.c line:129 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:131 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:134 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:137 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. LOG: lev:4 file:ael2_parse line:531 func: main 1 contexts, 1 extensions, 142 priorities asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest24/0000755000175000017500000000000011175405520020056 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest24/extensions.ael0000644000175000017500000000231111003201536022724 0ustar maniacmaniaccontext test11 { _X. => { Answer(); Dial(iax2/test11:nosecret@192.168.134.2522, 15,tTwW); Hangup(); NoOp($[{GROUP_COUNT(${target_num}@agent_queue_b)}=1]); NoOp($[1+0~~${DB(skip_group/${target_num}/agent_queue_b)}]); NoOp($[0~~${DB(skip_group/${target_num}/agent_queue_b)}+1]); NoOp($[${GROUP_COUNT(${target_num}@agent_queue_b)}=1+0~~${DB(skip_group/${target_num}/agent_queue_b)}]); NoOp($[${GROUP_COUNT(${target_num}@agent_queue_b)}=0~~${DB(skip_group/${target_num}/agent_queue_b)}+1]); if(${GROUP_COUNT(${target_num}@agent_queue_b)}==1+0~~${DB(skip_group/${target_num}/agent_queue_b)}) { Set(testif=$[1+0~~${DB(skip_group/${target_num}/agent_queue_b)}]); } if(${GROUP_COUNT(${target_num}@agent_queue_b)}==0~~${DB(skip_group/${target_num}/agent_queue_b)}+1) { Set(testif=$[1+0~~${DB(skip_group/${target_num}/agent_queue_b)}]); } if(${GROUP_COUNT(${target_num}@agent_queue_b)}==1+0~~${DB(skip_group/${target_num}/agent_queue_b)}) { Set(testif=$[1+0~~${DB(skip_group/${target_num}/agent_queue_b)}]); } } } asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-test150000644000175000017500000000171011021264016020366 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:115 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:pbx_ael.c line:128 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:131 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:134 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:139 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:142 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. LOG: lev:4 file:ael2_parse line:518 func: main 1 contexts, 0 extensions, 0 priorities asterisk-1.6.1.0/pbx/ael/ael-test/ael-test4/0000755000175000017500000000000011175405520017616 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-test4/apptest.ael20000644000175000017500000000662210423206707022052 0ustar maniacmaniac// this is a quick test to see how many of the apps we can spot j options in // include this in a macro or extension // at this moment, there are 18 apps that accept the j option. AddQueueMember(zork,iface,20,j); ADSIProg(sfile); AgentCallbackLogin(agent,s,30@cont); AgentLogin(agent,s); AgentMonitorOutgoing(dcn); AGI(whatever); AlarmReceiver(); Answer(2); AppendCDRUserField(value); Authenticate(pword,adjmr); BackGround(filename,snm,eng); BackgroundDetect(filename,20,2,10); Busy(10); ChangeMonitor(fnamebase); ChanIsAvail(Zap/5,sj); ChanSpy(prefix,bg()qrv); Congestion(5); ControlPlayback(filename,10,6,4,0,5,7,j); DateTime(unixtime,tz,fmt); DBdel(fam/key); DBdeltree(fam); DeadAGI(command); Dial(zap/1,45,A()CdD()fgG()hHjL()m()M()nNoprS()tTwW); Dictate(basedir); Directory(cont,dcont,f); DISA(68986869876,context); DumpChan(verblev); DUNDiLookup(90709780978,context,bj); EAGI(command); Echo(); EndWhile(); Exec(appname,args); ExecIf(expr,app,data); ExecIfTime(*,*,*,*,appname); ExternalIVR(command,arg1); Festival(text); Flash(); ForkCDR(v); GetCPEID(); Gosub(cont,exten,priority); GosubIf(cond?label); Goto(cont,exten,prior); GotoIf(cond?t:f); GotoIfTime(*,*,*,*?cont,ext,prior); Hangup(); HasNewVoicemail(vmbox,var,j); HasVoicemail(vmbox,var,j); IAX2Provision(template); ICES(xmlconfig); ImportVar(nevar@chann,var); Log(NOTICE,message); LookupBlacklist(j); LookupCIDName(); Macro(macro,arg1); MacroExit(); MacroIf(expr?etc); MailboxExists(mbox@cont,j); Math(v,2+2); MeetMe(5555,aAbcdDeimMpPqrstTovwxX); MeetMeAdmin(5555,e,user); MeetMeCount(5555,var); Milliwatt(); MixMonitor(filename,abv()V()W(),command); Monitor(file.fmt,base,mb); MP3Player(location); MusicOnHold(class); NBScat(); NoCDR(); NoOp(ignored); Page(Zap/1,dq); Park(exten); ParkAndAnnounce(template,5,238,retcont); ParkedCall(exten); PauseQueueMember(queue,zap,j); Pickup(ext@cont); Playback(file,j); PlayTones(arg); PrivacyManager(3,4,j); Progress(); Queue(queuename,dhHnrtTwW,http://www.where.what,over,5); Random(30,cont,ext,pri); Read(var,fname,10,skip,2,5); ReadFile(var=file,10); RealTime(fam,2,val,prefix); RealTimeUpdate(fam,2,val,2,newval); Record(file,2,10,anqst); RemoveQueueMember(queuename,iface,j); ResetCDR(wav); RetryDial(annound,4,2); Return(); Ringing(); RxFAX(fname,caller); SayAlpha(string); SayDigits(string); SayNumber(digits); SayPhonetic(string); SayUnixTime(unixtime,tz,fmt); SendDTMF(digits,10); SendImage(filename); SendText(text,j); SendURL(URL); Set(a=b); SetAMAFlags(); SetCallerID(clid,a); SetCallerPres(allowed_passed_screen); SetCDRUserField(value); SetGlobalVar(var=val); SetMusicOnHold(class); SetTransferCapability(SPEECH); SIPAddHeader(header); SIPDtmfMode(inband,info,rfc); SIPGetHeader(var@headername); SMS(name); SoftHangup(zap/1,a); StackPop(); StartMusicOnHold(class); StopMonitor(); StopMusicOnHold(); StopPlayTones(); System(command); TestClient(testid); TestServer(); Transfer(zap/1,j); TrySystem(command); TxFAX(filename,caller,debug); UnpauseQueueMember(queuename,iface,j); UserEvent(eventanme,body); Verbose(5,message); VMAuthenticate(mailbox@cont,s); VoiceMail(mailbox@cont,bg()suj); VoiceMailMain(mailbox@cont,pg()s); Wait(2); WaitExten(3,m()); WaitForRing(2); WaitForSilence(2,y); WaitMusicOnHold(2); While(expr); Zapateller(answer,5); ZapBarge(channel); ZapRAS(arg); ZapScan(group); ZapSendKeypadFacility(); asterisk-1.6.1.0/pbx/ael/ael-test/ael-test4/extensions.ael0000644000175000017500000000007710423206707022505 0ustar maniacmaniaccontext test1 { test2 => { #include "apptest.ael2"; } } asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-vtest170000644000175000017500000000367711122111676020601 0ustar maniacmaniac [dialextens] exten => _10X,1,Dial(Zap/${EXTEN:2},30,tw) exten => _1ZX,1,Dial(Zap/${EXTEN:1},30,tw) [dialthrus] exten => _3XX,1,Dial(Zap/${EXTEN:1},30,tw) [t1incoming] include => dialextens include => parkedcalls exten => s,1,Answer() exten => s,2,Background(welcome-to-test-machine) [incoming] include => dialextens include => parkedcalls exten => s,1,Answer() exten => s,2,Background(welcome-to-test-machine) [extension] include => dialextens include => dialthrus exten => 5,1,Record(recording:gsm) exten => 5,2,Background(recording) exten => 81,1,Set(iterations=$[1000000]) exten => 81,2,Set(time1=${EPOCH}) exten => 81,3,Set(i=$[1]) exten => 81,4,GotoIf($[${i}<${iterations}]?5:8) exten => 81,5,NoOp(Hello) exten => 81,6,Set(i=$[${i}+1]) exten => 81,7,Goto(4) exten => 81,8,NoOp(Finish for-extension-1) exten => 81,9,Set(time2=${EPOCH}) exten => 81,10,Verbose(The time diff is $[${time2} - ${time1} ] seconds) exten => 81,11,Verbose(Which means that the priorities/sec = $[4* ${iterations} / (${time2} - ${time1}) ]) exten => 81,12,SayNumber($[4 * ${iterations} / (${time2} - ${time1}) ]) exten => 82,1,Gosub(ndeep,s,1(100000)) exten => 82,2,Verbose(Finished 100000 levels deep call!) exten => 83,1,Set(~~EXTEN~~=${EXTEN}) exten => 83,2,Goto(sw-2-${~~EXTEN~~},10) exten => 83,3,NoOp(Finish switch-extension-2) exten => _sw-2-.,10,Goto(83,3) exten => sw-2-,10,Goto(sw-2-.,10) exten => _sw-2-[4-7]X,10,Verbose(and this too!) exten => _sw-2-[4-7]X,11,Goto(sw-2-.,10) exten => _sw-2-9X,10,Verbose(handle both 8x and 9x calls) exten => _sw-2-9X,11,Goto(sw-2-49,10) exten => _sw-2-8X,10,Verbose(do something to prepare it) exten => _sw-2-8X,11,Goto(sw-2-99,10) [ndeep] exten => s,1,Set(LOCAL(level)=${ARG1}) exten => s,2,GotoIf($[${level} == 0]?3:5) exten => s,3,Verbose(2|Got to Level 0) exten => s,4,Return() exten => s,5,NoOp(Finish if-ndeep-3) exten => s,6,Gosub(ndeep,s,1($[${level}-1])) exten => s,7,Return() [t1extension] include => dialextens include => dialthrus asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-ntest230000644000175000017500000000425510767746456020607 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -n option if you aren't interested in seeing all the instructions generated by the compiler) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:116 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:ael.flex line:672 func: setup_filestack --Read in included file ././t1/a.ael, 41 chars LOG: lev:2 file:ael.flex line:672 func: setup_filestack --Read in included file ././t1/b.ael, 42 chars LOG: lev:2 file:ael.flex line:672 func: setup_filestack --Read in included file ././t1/c.ael, 110 chars LOG: lev:4 file:ael.y line:774 func: ael_yyerror ==== File: ././t1/c.ael, Line 3, Cols: 10-10: Error: syntax error, unexpected '(', expecting '{' LOG: lev:2 file:ael.flex line:672 func: setup_filestack --Read in included file ././t2/d.ael, 41 chars LOG: lev:2 file:ael.flex line:672 func: setup_filestack --Read in included file ././t2/e.ael, 42 chars LOG: lev:2 file:ael.flex line:672 func: setup_filestack --Read in included file ././t2/f.ael, 82 chars LOG: lev:2 file:ael.flex line:672 func: setup_filestack --Read in included file ././qq.ael, 45 chars LOG: lev:2 file:ael.flex line:672 func: setup_filestack --Read in included file ././t3/g.ael, 41 chars LOG: lev:2 file:ael.flex line:672 func: setup_filestack --Read in included file ././t3/h.ael, 42 chars LOG: lev:2 file:ael.flex line:672 func: setup_filestack --Read in included file ././t3/i.ael, 41 chars LOG: lev:2 file:ael.flex line:672 func: setup_filestack --Read in included file ././t3/j.ael, 43 chars LOG: lev:4 file:ael.y line:774 func: ael_yyerror ==== File: ././t1/c.ael, Line 10, Cols: 10-10: Error: syntax error, unexpected '(', expecting '{' LOG: lev:2 file:pbx_ael.c line:129 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:4 file:pbx_ael.c line:145 func: pbx_load_module Sorry, but 2 syntax errors and 0 semantic errors were detected. It doesn't make sense to compile. LOG: lev:4 file:ael2_parse line:544 func: main 0 contexts, 0 extensions, 0 priorities asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-test50000644000175000017500000000270611021264016020313 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:115 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:pbx_ael.c line:128 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 130-183: The macro stdexten does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 185-192: The macro uvm does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 194-201: The macro bvm does not end with a return; I will insert one. LOG: lev:2 file:pbx_ael.c line:131 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:134 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:139 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:142 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. LOG: lev:4 file:ael2_parse line:518 func: main 38 contexts, 91 extensions, 494 priorities asterisk-1.6.1.0/pbx/ael/ael-test/ael-test6/0000755000175000017500000000000011175405520017620 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-test6/extensions.ael0000644000175000017500000004352010660336365022516 0ustar maniacmaniac/////////////////////////////////////////////////////////////////////////////// // Helpdesk Queue context hd-queue { s => { NoOp(Add a background sound to tell the user their options); Queue(helpdesk|t); NoOp(Put in options to apologize and send user to voicemail); }; 0 => goto default|0|1; 1 => { Dial(u41950@svm1.shsu.edu); Congestion(10); Hangup; }; }; context l903-calling { _9903NXXXXXX => { Realtime(l903_ext|exchange|${EXTEN:4:3}|l903_); if ("${l903_exchange}foo" = "foo") { Playback(num-outside-area); SayDigits(1); Playback(and-area-code); Playback(before-the-number); Hangup; }; &dialout(${EXTEN}); Congestion(10); Hangup; }; }; /////////////////////////////////////////////////////////////////////////////// // Extensions pulled from houston.conf // Converted the extension list to the database context houston-calling { _9713NXXXXXX => { Realtime(hou_713_ext|exchange|${EXTEN:4:3}|hou_713_); if ("${hou_713_exchange}foo" = "foo") { Playback(num-outside-area); SayDigits(1); Playback(and-area-code); Playback(before-the-number); Hangup; }; &dialout(${EXTEN}); Congestion(10); Hangup; }; _9281NXXXXXX => { Realtime(hou_281_ext|exchange|${EXTEN:4:3}|hou_281_); if ("${hou_281_exchange}foo" = "foo") { Playback(num-outside-area); SayDigits(1); Playback(and-area-code); Playback(before-the-number); Hangup; }; &dialout(${EXTEN}); Congestion(10); Hangup; }; _9832NXXXXXX => { Realtime(hou_832_ext|exchange|${EXTEN:4:3}|hou_832_); if ("${hou_832_exchange}foo" = "foo") { Playback(num-outside-area); SayDigits(1); Playback(and-area-code); Playback(before-the-number); Hangup; }; &dialout(${EXTEN}); Congestion(10); Hangup; }; }; /////////////////////////////////////////////////////////////////////////////// // Extensions pulled from huntsville.conf // Converted the extension list to the database context huntsville-calling { _9NXXXXXX => { Realtime(hv_ext|exchange|${EXTEN:1:3}|hv_); if ("${hv_exchange}foo" = "foo") { Playback(num-outside-area); SayDigits(1); Playback(and-area-code); Playback(before-the-number); Hangup; }; &dialout(${EXTEN}); Congestion(10); Hangup; }; _NXXXXXX => { NoOp(Stripping last four to see what extension we're dialing); Set(LAST4=${EXTEN:3}); StripLSD(4); }; i => Playback(pbx-invalid); h => Hangup; }; /////////////////////////////////////////////////////////////////////////////// // Extensions pulled from macros.conf macro dialout( number ) { Realtime(call_info|exten|${CALLERIDNUM:5}|mon_); if ("${mon_monitor}" = "YES") { Dial(SIP/${number}@sgw1.shsu.edu,,wW); Dial(SIP/${number}@sgw2.shsu.edu,,wW); } else { Dial(SIP/${number}@sgw1.shsu.edu); Dial(SIP/${number}@sgw2.shsu.edu); }; }; // Standard extension macro: // ${ext} - Extension macro stdexten( ext ) { Realtime(sipusers|name|${ext}|sip_user_); Realtime(call_info|exten|${ext}|info_); if ("${sip_user_name}foo" = "foo") { Wait(1); &dialout(${ext}); Congestion(10); Hangup; }; NoOp(${CALLERIDNUM}); RealtimeUpdate(call_info|exten|${ext}|calltrace|${CALLERIDNUM}); System(/usr/local/bin/db_update.sh call_info calltrace ${CALLERIDNUM} exten ${ext} &); &checkdnd(${ext}); &checkcf(${ext}); Realtime(call_info|exten|${CALLERIDNUM:5}|mon_); if ("${mon_monitor}" = "YES") { Dial(SIP/${info_forwardto},25,wW); } else { Dial(SIP/${info_forwardto},25); }; switch ("${DIALSTATUS}") { case "BUSY": &checkcfb(${ext}); break; case "CHANUNAVAIL": Dial(IAX2/asterisk:password@scm2.shsu.edu/${info_forwardto},25,wW); MailboxExists(${ext}); // if ("${VMBOXEXISTSSTATUS}" = "FAILED") { // Congestion(10); // Hangup; // }; &uvm(${ext}); Hangup; break; case "CONGESTION": MailboxExists(${ext}); if ("$(VMBOXEXISTSSTATUS}" = "FAILED") { Congestion(10); Hangup; }; &bvm(${ext}); Hangup; break; default: MailboxExists(${ext}); if ("$(VMBOXEXISTSSTATUS}" = "FAILED") { Congestion(10); Hangup; }; &uvm(${ext}); Hangup; }; Hangup; }; macro uvm( ext ) { Dial(SIP/u${ext}@svm1.shsu.edu); Playback(im-sorry); Playback(voice-mail-system); Playback(down); Congestion(10); Hangup; }; macro bvm( ext ) { Dial(SIP/b${ext}@svm1.shsu.edu); Playback(im-sorry); Playback(voice-mail-system); Playback(down); Congestion(10); Hangup; }; macro checkdnd( ext ) { if ("${info_donotdisturb}foo" = "foo") { NoOp(Do Not Disturb is not active); } else &uvm(${ext}); }; macro checkcf( ext ) { if ("${info_forwardto}foo" = "foo") if ("${ext}" = "43974") { Set(info_forwardto=${ext}&SCCP/${ext}); } else { Set(info_forwardto=${ext}&SIP/${ext}w); }; }; macro checkcfb( ext ) { if ("${info_forwardbusy}foo" = "foo") { Wait(1); MailboxExists(${ext}); if ("$(VMBOXEXISTSSTATUS}" = "FAILED") { &dialout(${ext}); Hangup; }; &bvm(${ext}); Hangup; }; &stdexten(${info_forwardbusy}); }; /////////////////////////////////////////////////////////////////////////////// // Extensions pulled from test.conf context test-include { includes { test-digium; test-sounds; test-phinfo; }; }; context test-digium { *500 => { Dial(IAX2/guest@misery.digium.com/s@default); Playback(demo-nogo); Hangup; }; }; context test-sounds { *501 => { Answer; Musiconhold; Wait(1); Hangup; }; }; context test-phinfo { *505 => { Answer; NoOp(${CALLERIDNUM:5}); SayDigits(${CALLERIDNUM:5}); Hangup; }; }; /////////////////////////////////////////////////////////////////////////////// // Extensions pulled from external.conf context long-distance { includes { local1; }; _91XXXXXXXXXX => &dialout(${EXTEN}); _9011. => &dialout(${EXTEN}); }; context local1 { includes { default; }; 911 => &dialout(911); 9911 => &dialout(9911); _9NXXXXXX => goto huntsville-calling|${EXTEN}|1; _936NXXXXXX => { Goto 9${EXTEN:3}|1; Congestion(10); Hangup; }; _832NXXXXXX => { goto 9${EXTEN}|1; Congestion(10); Hangup; }; _713NXXXXXX => { goto 9${EXTEN}|1 ; Congestion(10); Hangup; }; _281NXXXXXX => { goto 9${EXTEN}|1; Congestion(10); Hangup; }; _NXXNXXXXXX => { goto 9${EXTEN}|1; goto 91${EXTEN}|1; Congestion(10); Hangup; }; _91800NXXXXXX => &dialout(${EXTEN}); _91866NXXXXXX => &dialout(${EXTEN}); _91877NXXXXXX => &dialout(${EXTEN}); _91888NXXXXXX => &dialout(${EXTEN}); _91900NXXXXXX => &dialout(${EXTEN}); _91976NXXXXXX => &dialout(${EXTEN}); _9713NXXXXXX => goto houston-calling|${EXTEN}|1; _9281NXXXXXX => goto houston-calling|${EXTEN}|1; _9832NXXXXXX => goto houston-calling|${EXTEN}|1; _9903NXXXXXX => goto l903-calling|${EXTEN}|1; _31NXXNXXXXXX => &dialout(${EXTEN}); h => Hangup; }; /////////////////////////////////////////////////////////////////////////////// // Extensions pulled from internal.conf context from-scm2 { _4XXXX => { NoOp(DIALING SIP EXTENSION ${EXTEN} - FROM ${CALLERIDNUM}); Dial(SIP/${EXTEN},20,wW); Hangup; }; _6XXXX => { NoOp(DIALING SIP EXTENSION ${EXTEN} - FROM ${CALLERIDNUM}); Dial(SIP/${EXTEN},20,wW); Hangup; }; }; /////////////////////////////////////////////////////////// // All internal extensions work through the default context // Phones that can only make internal calls should be in // this context. /////////////////////////////////////////////////////////// context default { // Include the contexts in the files that allow us to make these phone calls includes { vm-include; apps-include; test-include; }; // ALWAYS have an 'h' extension h => { NoOp(Hangup cause was: ${HANGUPCAUSE}); Hangup; }; // We like to hear that we dialed an invalid extension i => Playback(pbx-invalid); // Dial the operator 0 => &dialout(0); // Send voicemail calls to the vm-* contexts to be handled voicemail => goto vm-direct|s|1; 5555 => goto vm-direct|s|1; 62100 => goto vm-extension|s|1; // These are our campus extensions, send them to the macro _6XXXX => &stdexten(${EXTEN}); _4XXXX => &stdexten(${EXTEN}); // These are campus extensions as well, might need to take this out though. _9294XXXX => goto _4XXXX|1; _9496XXXX => goto _6XXXX|1; // These allows us to dial from the directory in our phone without worrying about dialing 9 _936294XXXX => { goto ${EXTEN:5}|1; goto 9${EXTEN:3}|1; Congestion(10); Hangup; }; _936496XXXX => { goto ${EXTEN:5}|1; goto 9${EXTEN:3}|1; Congestion(10); Hangup; }; }; /////////////////////////////////////////////////////////////////////////////// // Extensions pulled from apps.conf context apps-include { includes { app-agents; app-dnd; app-callforward; app-calltrace; app-conferences; app-ssd; app-psd; app-idblock; app-helpdesk; app-dictate; app-set-monitor; }; }; context app-agents { *54 => { Answer; Wait(1); Read(agent_no|agent-user); AgentCallbackLogin(${agent_no}|s${CALLERIDNUM:5}); Playback(agent-loginok); Hangup; }; *55 => { Answer; Wait(1); AgentCallbackLogin(${agent_no}); Hangup; }; }; context app-calltrace { // caller dials this to find out the last call missed and possibly call back *69 => goto app-calltrace-perform|s|1; }; context app-calltrace-perform { s => { Answer; Wait(1); Background(info-about-last-call); Background(telephone-number); RealTime(call_info|exten|${CALLERIDNUM:5}|ct_); if ("${ct_calltrace}foo" = "foo") { Playback(loligo/from-unknown-caller); Hangup; } else { SayDigits("${ct_calltrace}"); Set(TIMEOUT(digit)=3); Set(TIMEOUT(response)=7); Background(loligo/to-call-this-number); Background(press-1); Background(loligo/silence/5); }; }; 1 => goto local1|${ct_calltrace}|1; i => { Playback(vm-goodbye); Hangup; }; t => { Playback(vm-goodbye); Hangup; }; }; context app-set-monitor { *50 => { Realtime(call_info|exten|${CALLERIDNUM:5}|mon_set_); if ("${mon_set_monitor}" = "YES") { RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|monitor|); System(/usr/local/bin/db_update.sh call_info monitor '' exten ${CALLERIDNUM:5} &); } else { RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|monitor|YES); System(/usr/local/bin/db_update.sh call_info monitor YES exten ${CALLERIDNUM:5} &); }; NoOp(${mon_set_monitor}); Hangup; }; }; context app-dnd { *78 => { Answer; Wait(1); RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|donotdisturb|YES); System(/usr/local/bin/db_update.sh call_info donotdisturb YES exten ${CALLERIDNUM:5} &); Playback(do-not-disturb); Playback(loligo/activated); Hangup; }; *79 => { Answer; Wait(1); RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|donotdisturb|); System(/usr/local/bin/db_update.sh call_info donotdisturb '' exten ${CALLERIDNUM:5} &); Playback(do-not-disturb); Playback(loligo/de-activated); Hangup; }; }; context app-callforward { // forwards calling extension to input number *72{EXTEN} _*72. => { RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|forwardto|${EXTEN:3}); System(/usr/local/bin/db_update.sh call_info forwardto ${EXTEN:3} exten ${CALLERIDNUM:5} &); Answer; Wait(1); Playback(loligo/call-fwd-unconditional); Playback(loligo/for); Playback(loligo/extension); SayDigits(${CALLERIDNUM:5}); Playback(loligo/is-set-to); SayDigits(${EXTEN:3}); Hangup; }; // prompts for extension to forward to *72 => { Answer; Wait(1); Playback(please-enter-your); Playback(extension); Background(then-press-pound); VMAuthenticate(|s); Background(loligo/ent-target-attendant); Read(toext,loligo/then-press-pound); Wait(1); RealtimeUpdate(call_info|exten|${AUTH_MAILBOX}|forwardto|${toext}); System(/usr/local/bin/db_update.sh call_info forwardto ${toext} exten ${AUTH_MAILBOX} &); Playback(loligo/call-fwd-unconditional); Playback(loligo/for); Playback(loligo/extension); SayDigits(${AUTH_MAILBOX}); Playback(loligo/is-set-to); SayDigits(${toext}); Hangup; }; // cancels dialed extension call forward _*73. => { Realtime(voicemail|mailbox|${EXTEN:3}|auth_); Answer; Wait(1); Authenticate(${auth_password}); RealtimeUpdate(call_info|exten|${EXTEN:3}|forwardto|); System(/usr/local/bin/db_update.sh call_info forwardto '' exten ${EXTEN:3} &); Wait(1); SayDigits(${EXTEN:3}); Playback(loligo/call-fwd-cancelled); Hangup; }; // cancels call forward for calling extension *73 => { RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|forwardto|); System(/usr/local/bin/db_update.sh call_info forwardto '' exten ${CALLERIDNUM:5} &); Answer; Wait(1); Playback(loligo/call-fwd-cancelled); Hangup; }; // dialed call forward on busy _*90. => { RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|forwardbusy|${EXTEN:3}); System(/usr/local/bin/db_update.sh call_info forwardbusy ${EXTEN:3} exten ${CALLERIDNUM:5} &); Answer; Wait(1); Playback(loligo/call-fwd-on-busy); Playback(loligo/for); Playback(loligo/extension); SayDigits(${CALLERIDNUM:5}); Playback(loligo/is-set-to); SayDigits(${EXTEN:3}); Hangup; }; // cancels call forward on busy for calling extension *91 => { RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|forwardbusy|); System(/usr/local/bin/db_update.sh call_info forwardbusy '' exten ${CALLERIDNUM:5} &); Answer; Wait(1); Playback(loligo/call-fwd-on-busy); Playback(loligo/de-activated); Hangup; }; h => Hangup; }; context app-idblock { _*67. => { Set(CALLERID(name)=Anonymous); &stdexten(${EXTEN:3}); }; }; context app-dictate { *1 => { Dictate(); Hangup; }; }; context app-ssd { // *59 - Set system speed dial to digits // *59 0 - Delete system speed dial // *59 - Review system speed dial // *1xx - Dial speed dial _*59XXX. => { Answer; RealtimeUpdate(ssd|sd|${EXTEN:3:2}|extension|${EXTEN:5}); System(/usr/local/bin/db_update.sh systemsd extension ${EXTEN:5} sd ${EXTEN:3:2} &); Wait(1); Playback(loligo/speed-dial); SayDigits(${EXTEN:3:2}); Playback(loligo/has-been-set-to); SayDigits(${EXTEN:5}); Hangup; }; _*59XX0 => { Answer; RealtimeUpdate(ssd|sd|${EXTEN:3:2}|extension|); System(/usr/local/bin/db_update.sh systemsd extension '' sd ${EXTEN:3:2} &); Wait(1); Playback(loligo/speed-dial); SayDigits(${EXTEN:3:2}); Playback(loligo/has-been-cleared); Hangup; }; _*59XX => { Answer; Realtime(ssd|sd|${EXTEN:3}|ssd_); if ("${ssd_extension}foo" = "foo") { Playback(loligo/speed-dial); SayDigits(${EXTEN:3:2}); Playback(loligo/is-not-set); Hangup; }; Wait(1); Playback(loligo/speed-dial); SayDigits(${EXTEN:3:2}); Playback(loligo/is-set-to); SayDigits(${ssd_extension}); Hangup; }; // NTC = number to call _*1XX => { Realtime(ssd|sd|${EXTEN:2}|ssd_); if ("${ssd_extension}foo" = "foo") { Answer; Wait(1); Playback(loligo/speed-dial); SayDigits(${EXTEN:2}); Playback(loligo/is-not-set); Hangup; }; &stdexten(${ssd_extension}); Congestion(10); Hangup; }; }; macro check-psd-exists ( ext ) { Realtime(psd|extension|${ext}|psd_); if ("${psd_extension}foo" = "foo") { System(/usr/local/bin/create_psd.sh ${ext}); } else NoOp(PSD set for ${ext}); }; context app-psd { // *89 - Set personal speed dial to digits // *89 0 - Delete personal speed dial // *89 - Review personal speed dial // *2xx - Dial personal speed dial _*89XXX. => { &check-psd-exists(${CALLERIDNUM:5}); Answer; RealtimeUpdate(psd|extension|${CALLERIDNUM:5}|s${EXTEN:3:2}|${EXTEN:5}); System(/usr/local/bin/db_update.sh personalsd s${EXTEN:3:2} ${EXTEN:5} extension ${CALLERIDNUM:5} &); Wait(1); Playback(loligo/speed-dial); SayDigits(${EXTEN:3:2}); Playback(loligo/has-been-set-to); SayDigits(${EXTEN:5}); Hangup; }; _*89XX0 => { &check-psd-exists(${CALLERIDNUM:5}); Answer; RealtimeUpdate(psd|extension|${CALLERIDNUM:5}|s${EXTEN:3:2}|); System(/usr/local/bin/db_update.sh personalsd s${EXTEN:3:2} '' extension ${CALLERIDNUM:5} &); Wait(1); Playback(loligo/speed-dial); SayDigits(${EXTEN:3:2}); Playback(loligo/has-been-cleared); Hangup; }; _*89XX => { &check-psd-exists(${CALLERIDNUM:5}); Answer; Realtime(psd|extension|${CALLERIDNUM:5}|psd_); Wait(1); if ("${psd_s${EXTEN:3:2}}foo" = "foo") { Playback(loligo/speed-dial); SayDigits(${EXTEN:3:2}); Playback(loligo/is-not-set); Hangup; }; Playback(loligo/speed-dial); SayDigits(${EXTEN:3:2}); Playback(loligo/is-set-to); SayDigits(${psd_s${EXTEN:3:2}}); Hangup; }; // NTC = number to call _*2XX => { &check-psd-exists(${CALLERIDNUM:5}); Realtime(psd|extension|${CALLERIDNUM:5}|psd_); if ("${psd_s${EXTEN:2}}foo" = "foo") { Answer; Wait(1); Playback(loligo/speed-dial); SayDigits(${EXTEN:2}); Playback(loligo/is-not-set); Hangup; }; &stdexten(${psd_s${EXTEN:2}}); Congestion(10); Hangup; }; }; context app-helpdesk { *4357 => { &stdexten(41950); Congestion; }; }; context app-conferences { // waiting for room number announcement *86 => goto app-conf-hidden|s|1; }; context app-conf-hidden { s => { Wait(1); Playback(loligo/please-enter-the); Playback(loligo/extension); read(roomtoenter,loligo/then-press-pound); Meetme(${roomtoenter}); Waitexten(8); Hangup; }; _1. => Meetme(${EXTEN}); }; /////////////////////////////////////////////////////////////////////////////// // Extensions pulled from vm.conf: context vm-include { includes { vm-direct; vm-extension; vm-directory; }; }; context vm-direct { s => { Dial(SIP/5555@svm1.shsu.edu,20); Playback(im-sorry); Playback(voice-mail-system); Playback(down); Playback(extra/pls-try-call-later); Congestion(10); Hangup; }; }; context vm-extension { s => { Dial(SIP/62100@svm1.shsu.edu,20); Playback(im-sorry); Playback(voice-mail-system); Playback(down); Playback(extra/pls-try-call-later); Congestion(10); Hangup; }; }; context vm-directory { 5556 => { Dial(SIP/5556@svm1.shsu.edu); Playback(im-sorry); Playback(voice-mail-system); Playback(down); Playback(extra/pls-try-call-later); Congestion(10); Hangup; }; }; asterisk-1.6.1.0/pbx/ael/ael-test/ael-test15/0000755000175000017500000000000011175405520017700 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-test15/extensions.ael0000644000175000017500000000032510475447433022575 0ustar maniacmaniac/* and some comments would make a nice touch */ context t1 { /* this a test of block comments */ _15x => { /* more comments across several lines * what do you think* */ } } /* amd some more */ asterisk-1.6.1.0/pbx/ael/ael-test/ael-test16/0000755000175000017500000000000011175405520017701 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-test16/extensions.ael0000644000175000017500000000003110511006221022541 0ustar maniacmaniaccontext real-small { } asterisk-1.6.1.0/pbx/ael/ael-test/ael-test11/0000755000175000017500000000000011175405520017674 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-test11/extensions.ael0000644000175000017500000000155610506371722022570 0ustar maniacmaniaccontext test1 { s => { goto lab1; if( ${testnotnull} ) { lab1: NoOp(hello); } else { lab1: MoOp(goodbye); } } 1 => { lab1: NoOp(This one is OK.); } } macro endcall5(type) { switch(${type}) { case out: if(${testnotnull}) { NoOp(whoosh); goto ptr1 ; // <-- goto call to valid label } case in: ptr1: // The First label is the valid one... if(${testnotnull}) { NoOp(wow); goto ptr1 ; // <-- goto call to valid label } Noop(esac) ; } if(${testnotnull}) { goto ptr1; } switch(${type}) { case out: switch(${type}) { case in: if(${testnotnull}) { ptr1: // <-- duplicate label (macros are about the equiv of an extension) Softhangup(${CHANNEL}); break ; } Noop(esac) ; } } return; } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest9/0000755000175000017500000000000011175405517020007 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest9/extensions.ael0000755000175000017500000000033710453311556022674 0ustar maniacmaniac context workext { ignorepat => 8; ignorepat => 9; 793 => { Set(QUERYSTRING=SELECT\ foo\,\ bar\ FROM\ foobar); Verbose(2|${QUERYSTRING}); query="SELECT foo\, bar FROM foobar" ; Verbose(2|${query}) ; } } asterisk-1.6.1.0/pbx/ael/ael-test/ael-test18/0000755000175000017500000000000011175405520017703 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-test18/extensions.ael0000644000175000017500000000173410602044020022556 0ustar maniacmaniaccontext default { 706/3077610011 => { JabberStatus(asterisk|jmls@mike,StatusCode); switch(${StatusCode}) { case 1: Dial(SIP/706,12); switch(${DIALSTATUS}) { case BUSY: Voicemail(b706); break; default: Voicemail(u706); }; BackGround(hello); break; default: Voicemail(u706); }; ifTime(3:00-13:00|*|*|*) { NoOp(hello); label1: NoOp(goodbye); } else { NoOp(hithere); label2: NoOp(whatonearth?); } goto label1; goto label2; Hangup(); }; } asterisk-1.6.1.0/pbx/ael/ael-test/ael-test7/0000755000175000017500000000000011175405520017621 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-test7/extensions.ael0000644000175000017500000002506110722651651022514 0ustar maniacmaniac// // Example AEL config file // globals { CONSOLE=Console/dsp; TRUNKMSD=0; //MSD digits to strip (usually 1 or 0) TRUNCPROTO=SIP; TRUNK=sunrocket; PSTN=pstn-spa3k; PSTNPROTO=SIP; TARIOPROTO=SIP; TARIO=tario; CPPROTO=SIP; CPACKET1=callpacket1; CPACKET2=callpacket2; SELLVOIP=1577040314; SVPROTO=IAX2; }; macro stdexten (ext , dev ) { PrivacyManager(3,10); if("${PRIVACYMGRSTATUS}" = "FAILED") { Playback(vm-goodbye); Hangup(); }; AGI(calleridnamelookup.agi); Dial(${dev}/${ext},30,t); switch(${DIALSTATUS}) { case BUSY: Voicemail(b${ext}); break; default: Voicemail(u${ext}); }; catch a { VoiceMailMain(${ext}); return; }; }; macro announce_minutes(minutes) { Playback(vm-youhave); SayNumber(${minutes}); Playback(vm-minutes); Wait(1); }; // Check if given provider allows only some free minutes per month // and announce number of free minutes remaining. // The limit will be reset monthly by cron job. // The macro sets the following variables: // MINUTES_LIMIT - number of free minutes per month // MINUTES_USED - number of free minutes used in the current month // PROVIDER - provider name macro checkanddial(prov,proto,ext,arg1,arg2,arg3,arg4) { Set(MINUTES_LIMIT=0); Set(MINUTES_USED=0); Set(PROVIDER=${prov}); if(${DB_EXISTS(Provider/${prov}/used)}) Set(MINUTES_USED=${DB_RESULT}); country_c = 0; switch(${LEN(${ext})}) { //assuming all international numbers are 11 digits long. case 10: //NXXNXXXXXX country_c=1; break; case 11: //XNXXNXXXXXX country_c = ${ext:0:1}; break; default: //011XNXXNXXXXXX country_c = ${ext:3:1}; break; }; if("${prov}" = "${TRUNK}" & ${country_c} != 1) { // SunRocket international calls Set(MINUTES_LIMIT=${DB(Provider/${prov}/limit)}); &announce_minutes($[${MINUTES_LIMIT} - ${MINUTES_USED}]); }; if("${prov}" = "${CPACKET1}" | "${prov}" = "${CPACKET2}") { // Callpacket has a limit on domestic calls Set(MINUTES_LIMIT=${DB(Provider/${prov}/limit)}); &announce_minutes($[${MINUTES_LIMIT} - ${MINUTES_USED}]); }; DeadAGI(dial.agi,${proto}/${ext}@${prov},${arg1},${arg2},${arg3},${arg4}); }; macro trunkdial(ext) { // Dial sunrocket and set correct collerid if("${CALLERID(num)}" = "1") { Set(CALLERID(num)=7322271653); } else { Set(CALLERID(num)=7326260100); }; Set(CALLERID(name)=Sergey Okhapkin); &checkanddial(${TRUNK},${TRUNCPROTO},${ext},60,T); Hangup; }; macro checklocal(ext) { // lookup the number in DB and call the number via pstn or sunrocket Set(AREACODE=${ext:0:3}); Set(EXCHANGE=${ext:3:3}); Set(IS_LOCAL=${DB_EXISTS(localnum/${AREACODE}/${EXCHANGE})}); if(${IS_LOCAL}) { &checkanddial(${PSTN},${PSTNPROTO},${ext},60,T); if ("${DIALSTATUS}" = "BUSY") &trunkdial(${ext}); } else &trunkdial(${ext}); }; macro autodial(ext) { // Find Least Cost Route LCDial(${ext},60,T); if("${DIALSTATUS}" = "NOPROVIDER") Playback(invalid); Hangup(); }; context default { // Calls to us s => { Wait(1); Answer; start: Set(TIMEOUT(digit)=3); Set(TIMEOUT(response)=10); repeat: for (x=0; ${x} < 5; x=${x} + 1) { Background(home/greeting); WaitExten(); }; }; t => jump *; i => { // invalid extension Playback(invalid); goto s|repeat; }; _* => { Playback(vm-goodbye); Wait(1); Hangup; }; 1 => &stdexten(1,SIP/1); 2 => &stdexten(2,SIP/2); 3 => &stdexten(3,SIP/3); 2271653 => jump 1; 7322271653 => jump 1; 17322271653 => jump 1; 6260100 => jump 2; 7326260100 => jump 2; 17326260100 => jump 2; 8058701100 => jump 2; 3103622835 => jump 2; sos => jump 2; 1400898 => jump 2; 6260101 => jump s; 7326260101 => jump s; 17326260101 => jump s; 2271677 => jump 3; 7322271677 => jump 3; 17322271677 => jump 3; galka => jump 3; 911 => Dial(${PSTNPROTO}/911@${PSTN},60,); 380 => Dial(SIP/topspeen@212.40.38.70,60,T); // Fun stuff 100 => { SayUnixTime(); goto s|start; }; 101 => { // Voicemail VoicemailMain(${CALLERID(num)}); Hangup; }; 102 => MusicOnHold(); // 103 => { // Wait(1); //start: // Read(NUMBER,vm-enter-num-to-call); // LCDial(${NUMBER},T); // goto start; // }; 105 => jump s@phrase-menu; 7312 => { ForkCDR; Set(CALLERID(name)=Sergey Okhapkin); Set(CALLERID(num)=7326260100); DISA(1111|home); }; }; context goiax { s => { Answer(); Ringing(); Wait(1); start: Read(NUMBER,vm-enter-num-to-call); Set(CALLERID(name)=Central NJ); Dial(IAX2/14301@fwdOUT/q${NUMBER},60,T); goto start; }; }; context phrase-menu { s => { Answer; // Answer the line TIMEOUT(digit)=2; // Set Digit Timeout to 5 seconds TIMEOUT(response)=10; // Set Response Timeout to 10 seconds BackGround(custom/phrase-menu); // Play main menu. }; 1 => { // Phrase Recording Wait(1); Read(PHRASEID|custom/enter-phrase-num); Wait(2); // give yourself 2 secs to take a breath and wait for beep Record(custom/${PHRASEID}:gsm); Wait(2); Playback(custom/${PHRASEID}); Wait(1); jump s; }; 2 => { // Phrase review Wait(1); Read(PHRASEID|custom/enter-phrase-num); Wait(1); Playback(custom/${PHRASEID}); Wait(1); jump s; }; t => Hangup; i => { Playback(custom/invalid-option); jump s; }; }; context outbound { // North America seven-, ten- and eleven digits _NXXXXXX => &autodial(1732${EXTEN}); _NXXNXXXXXX => &autodial(1${EXTEN}); _ZNXXNXXXXX. => &autodial(${EXTEN}); // Toll free numbers via PSTN // _1800NXXXXXX => &checkanddial(${PSTN},${PSTNPROTO},${EXTEN},60,T); // _1888NXXXXXX => &checkanddial(${PSTN},${PSTNPROTO},${EXTEN},60,T); // _1877NXXXXXX => &checkanddial(${PSTN},${PSTNPROTO},${EXTEN},60,T); // _1866NXXXXXX => &checkanddial(${PSTN},${PSTNPROTO},${EXTEN},60,T); _011. => { //International context accessed through trunk &trunkdial(${EXTEN}); }; _012. => { //fwdOUT Set(CALLERID(name)=Central NJ); Dial(IAX2/14301@fwdOUT/q${EXTEN:3},60,T); }; _013X. => { //NECC Dial(${PSTNPROTO}/011${EXTEN:3}@${PSTN},60,T); }; _0131. => { //NECC to US Dial(${PSTNPROTO}/${EXTEN:3}@${PSTN},60,T); }; _014. => { //TARIO by SIP ID Set(CALLERID(name)=Sergey Okhapkin); Set(CALLERID(num)=1400898); Dial(${TARIOPROTO}/${EXTEN:3}@${TARIO},60,T); }; _0157. => { //TARIO outbound Russia Set(CALLERID(name)=Sergey Okhapkin); Set(CALLERID(num)=1400898); Dial(${TARIOPROTO}/8${EXTEN:4}@${TARIO},60,T); }; // _015. => { //TARIO outbound international // CALLERID(name)="Sergey Okhapkin"; // CALLERID(num)=1400898; // Dial(${TARIOPROTO}/810${EXTEN:3}@${TARIO},60,T); // }; _0161NXXNXXXXXX => { //Callpacket outbound USA/Canada &checkanddial(${CPACKET1},${CPPROTO},${EXTEN:3},60,T); }; _0171NXXNXXXXXX => { //Callpacket outbound USA/Canada &checkanddial(${CPACKET2},${CPPROTO},${EXTEN:3},60,T); }; _0181NXXNXXXXXX => { //sellvoip outbound USA/Canada Dial(${SVPROTO}/${SELLVOIP}@${SELLVOIP}/${EXTEN:3},60,T); }; _019. => { //Voipbuster Dial(IAX2/sokhapkin@voipbuster/00${EXTEN:3},60,T); }; }; context home { //calls from us includes { default; outbound; }; }; context sunrocket-in { 7322271653 => jump s; 7326260100 => jump 2@default; s => { if("${CALLERID(num)}" = "sunrocketcom") Set(CALLERID(num)=); switch(${CALLERID(RDNIS)}) { case 7326260100: jump 2@default; break; case 7326260101: jump s@default; break; default: jump 1@default; break; }; }; }; context pstn-in { 3 => { if ("${CALLERID(num)}" = "7322271677") Set(CALLERID(num)=); jump 3@default; }; }; context tario.net-in { _X. => { Set(CALLERID(name)=); if("${CALLERID(num):-11:1}" = "8") Set(CALLERID(num)=7${CALLERID(num):1}); if("${SIP_HEADER(To)}" = "") { jump 3@default; } else if("${SIP_HEADER(To)}" = "") { jump 1@default; } else jump 2@default; }; }; context from-callpacket { 8058701100 => jump 2@default; 3103622835 => { Answer; Ringing; Wait(10); Voicemail(b3103622835); Hangup; }; a => Hangup; }; context fromfwdOUT { // make sure we only accept US and Canada calls, limit to 30 minutes includes { fromfwdOUT-catchbad; fromfwdOUT-isgood; fromfwdOUT-catchall; }; }; context fromfwdOUT-isgood { _17326260100 => jump 2@default; _17326260101 => jump s@default; _17322271653 => jump 1@default; _17322271677 => jump 3@default; _1NXXNXXXXXX => { Set(CALLERID(name)=Sergey Okhapkin); // Set(CALLERID(num)=7326260100); // Dial(${TRUNCPROTO}/*67${EXTEN:${TRUNKMSD}}@${TRUNK},60,,L(1800000:60000)); Dial(${CPPROTO}/${EXTEN}@${CPACKET2},60,,L(1800000:60000)); }; }; context fromfwdOUT-catchbad { //block bahamas, etc _1900. => congestion ; //N11 _1XXX976. => congestion ; //N11 _1XXX555. => congestion ; //N11 _1X11. => congestion ; //N11 _1867. => congestion ; //Yukon (sorry mike) // exten => _1NPA Country _1242. => congestion; //BAHAMAS _1246. => congestion; //BARBADOS _1264. => congestion; //ANGUILLA _1268. => congestion; //ANTIGUA/BARBUDA _1284. => congestion; //BRITISH VIRGIN ISLANDS _1345. => congestion; //CAYMAN ISLANDS _1441. => congestion; //BERMUDA _1473. => congestion; //GRENADA _1649. => congestion; //TURKS & CAICOS ISLANDS _1664. => congestion; //MONTSERRAT _1758. => congestion; //ST. LUCIA _1767. => congestion; //DOMINICA _1784. => congestion; //ST. VINCENT & GRENADINES _1809. => congestion; //DOMINICAN REPUBLIC _1829. => congestion; //DOMINICAN REPUBLIC _1868. => congestion; //TRINIDAD AND TOBAGO _1869. => congestion; //ST. KITTS AND NEVIS _1876. => congestion; //JAMAICA _1787. => congestion; //Puerto Rico 787, 939 $0.07 _1939. => congestion; //Puerto Rico 787, 939 $0.07 _1671. => congestion; //Guam 671 $0.08 _1340. => congestion; //U.S. Virgin Islands 340 $0.06 }; context fromfwdOUT-catchall { _X. => Congestion; h => Hangup ; //hangup event i => Hangup ; //invalid event t => Hangup ; //timeout event }; context ael-demo { s => { Wait(1); Answer(); TIMEOUT(digit)=5; TIMEOUT(response)=10; restart: Background(demo-congrats); instructions: for (x=0; ${x} < 3; x=${x} + 1) { Background(demo-instruct); WaitExten(); }; }; 2 => { Background(demo-moreinfo); goto s|instructions; }; 3 => { LANGUAGE()=fr; goto s|restart; }; 500 => { Playback(demo-abouttotry); Dial(IAX2/guest@misery.digium.com); Playback(demo-nogo); goto s|instructions; }; 600 => { Playback(demo-echotest); Echo(); Playback(demo-echodone); goto s|instructions; }; _1234 => &std-exten-ael(${EXTEN}, "IAX2"); # => { Playback(demo-thanks); Hangup(); }; t => jump #; i => Playback(invalid); }; asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-test80000644000175000017500000000171111046713743020326 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:115 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:pbx_ael.c line:128 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:131 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:134 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:139 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:142 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. LOG: lev:4 file:ael2_parse line:518 func: main 1 contexts, 7 extensions, 18 priorities asterisk-1.6.1.0/pbx/ael/ael-test/ael-vtest21/0000755000175000017500000000000011175405520020063 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-vtest21/extensions.ael0000644000175000017500000000032010660336365022750 0ustar maniacmaniacglobals { AXLHAFT=wow-to-the-tenth-power; JibberWorthy=zinger3; OFFICE_CODE=503; } context from-enum { _${OFFICE_CODE}XXXX => { Answer(); goto ${EXTEN:3}|1; } } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest23/0000755000175000017500000000000011175405520020055 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest23/t3/0000755000175000017500000000000011175405520020403 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest23/t3/j.ael0000644000175000017500000000005310767746456021343 0ustar maniacmaniac context j { 567 => NoOp(hi there, j); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest23/t3/i.ael0000644000175000017500000000005110767746456021340 0ustar maniacmaniaccontext i { 134 => NoOp(hi there, i); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest23/t3/g.ael0000644000175000017500000000005110767746456021336 0ustar maniacmaniaccontext g { 134 => NoOp(hi there, g); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest23/t3/h.ael0000644000175000017500000000005210767746456021340 0ustar maniacmaniac context h { 456 => NoOp(hithere, h); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest23/t2/0000755000175000017500000000000011175405520020402 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest23/t2/d.ael0000644000175000017500000000005110767746456021332 0ustar maniacmaniaccontext d { 134 => NoOp(hi there, d); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest23/t2/e.ael0000644000175000017500000000005210767746456021334 0ustar maniacmaniac context e { 456 => NoOp(hithere, e); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest23/t2/f.ael0000644000175000017500000000012210767746456021333 0ustar maniacmaniac#include "qq.ael" context f { 567 => NoOp(hi there, f); } #include "t3/*.ael" asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest23/t1/0000755000175000017500000000000011175405520020401 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest23/t1/a.ael0000644000175000017500000000005110767746456021326 0ustar maniacmaniaccontext a { 134 => NoOp(hi there, a); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest23/t1/b.ael0000644000175000017500000000005210767746456021330 0ustar maniacmaniac context b { 456 => NoOp(hithere, b); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest23/t1/c.ael0000644000175000017500000000015610767746456021336 0ustar maniacmaniac context c() { 567 => NoOp(hi there, c); } #include "t2/*.ael" context w() { 890 => NoOp(hi there, w); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest23/qq.ael0000644000175000017500000000005510767746456021207 0ustar maniacmaniac context qq { 567 => NoOp(hi there, qq); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest23/extensions.ael0000644000175000017500000000013410767746456022763 0ustar maniacmaniac#include "t1/*.ael" context z () { 123 => NoOp(hi there, z); 124 => NoOp(hi there, z); } asterisk-1.6.1.0/pbx/ael/ael-test/ael-test3/0000755000175000017500000000000011175405520017615 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-test3/telemarket_torture.ael20000755000175000017500000006660410475447433024335 0ustar maniacmaniac// // AN EXCERSIZE IN BAD DIALPLAN DESIGN // (What better testing ground than on telemarketers?) // // BAD DESIGN: long, boring introductions followed by long, drawn out menus of choices. // if they survive to the last option, how will they remember the choices? // // BAD DESIGN: Amateur Recording. Poor voice quality, too quiet. // Also, the announcer is definitely not vocally gifted. // Also, the long pauses and clicks between the intro // and menu choices might lead some to think that // the announcements are over, and hang up. Too bad! // WORSE DESIGN: Instead of using the Background application, the Playback // application is used. After taking so much time and trouble // to record this material, the caller must listen and enjoy // every syllable before they can make an option choice. None // of that interrupting with a choice. We want them to savour // every word! // GOOD/BAD, ER INSIDIOUS -- DANGLE A CARROT-- GIVE THE LISTENER A GOOD REASON TO // HANG ON AND VOLUNTARILY LISTEN TO THE TORTURE. // BUT, DON'T MAKE PROMISES YOU WON'T KEEP! context telemarket { s => { begin: Playback(telemarketer-intro); // ; Script: // Due to the extremely high volume of calls from everything from telemarketers // to Septic System Bacteria vendors, we are asking all such organizations // to remove this number from their call list, or as need be, to add this // number to their No-Call list, whichever is relevent. // [THE CARROT:] // We HAVE made some exceptions, and if you wish to see if your organization // has been exempted, please listen to and follow the following prompts. // // Otherwise, please Cease calling this number! // Playback(telemarketer-choices); // if you represent a charitable organization, please dial 1, // if you represent a political organization, please dial 2. // if you represent a polling company, please dial 3, // if you represent a market research organization, please dial 4. // if you represent a magazine or newsletter, please dial 5. // if you represent a commercial organization, please dial 6. } 1 => goto telemarket-charity|s|begin; 2 => goto telemarket-political|s|begin; 3 => goto telemarket-pollster|s|begin; 4 => goto telemarket-research|s|begin; 5 => goto telemarket-magazine|s|begin; 6 => goto telemarket-commercial|s|begin; 7 => goto telemarket-other|s|begin; t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemarket-charity { s => { begin: Playback(telemark-charity-intro); // We have contributed generously to many worthy causes in the past, and will // continue to do so in the future. But we suspect that such organizatons // have sold our name and phone number to each other until we are now hounded // day and night by literally hundreds of such organizations. // Enough is Enough! // // If we have contributed to your cause in the past, we may, perhaps, be disposed to // do so in the future, at our option, // we give no pledges nor make any commitments here. // Send us material via the post if you feel this necessary // but do not even consider email. Any email or further phone calls from your organization // in the future, will be considered an act of aggression, and we will // blacklist your organization for the rest of our natural lives. // // To see if your organization is exempt from these prohibitions, please // comply with the following options. Playback(telemark-charity-choices); // If your organization is disease or genetic defect related, dial 1, // If your organization is handicap related, dial 2. // If your organization is a police or fireman or other similar support entity, please dial 3. // If your organization is a grade school to high school related // fund raiser or other type of activity, please dial 4. // If your organization is a college or univerity or alumnis organization, please dial 5. // If your organization is animal rights or ecology related organization, please dial 6. // If your organization is a political action or candidate support related, please dial 7. // If your organization is a substance abuse related organization or cause, please dial 8. // And any other charity or tax exempt organization should dial 9. } 1 => goto telemarket-char-disease|s|begin; 2 => goto telemarket-char-handicap|s|begin; 3 => goto telemarket-char-police|s|begin; 4 => goto telemarket-char-school|s|begin; 5 => goto telemarket-char-college|s|begin; 6 => goto telemarket-char-animal|s|begin; 7 => goto telemarket-char-candidate|s|begin; 8 => goto telemarket-char-abuse|s|begin; 9 => goto telemarket-char-other|s|begin; // BAD DESIGN: referring all timeouts,invalid choices, etc, back to the root of the menu tree will frustrate users no end! // WORSE DESIGN: How about having the user have to push a button to repeat the current menu? When a time out could just // automatically do it for the user? t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemarket-char-disease { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-char-handicap { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-char-police { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-char-school { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-char-college { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-char-animal { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-char-candidate { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-char-abuse { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-char-other { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-sorry { s => { begin: Playback(telemarket-sorry); // Sorry -- your organization is not exempt. Please stop calling us. // Thank you. goodbye. Hangup(); } } // BAD DESIGN: Hanging up on your audience, no matter what the outcome, is not a nice thing to do! context telemarket-exception { s => { begin: Playback(telemarket-success); // Congratulations. Your organization IS exempt. Please call us back, // but this time, just act like a normal caller. Thank you. Goodbye. Hangup(); } } // BAD DESIGN: Making long cascading menu choices is a nasty thing to do to callers! // BAD DESIGN: Putting the most frequently encountered items at the end of a list is also a nasty thing to do! // GOOD DESIGN: All rejection notices use a single context. All Acceptance also. To change a rejection to an // acceptance, just change the reference from telemarket-sorry to telemarket-exception context telemarket-political { s => { begin: Playback(telemark-polit-intro); // To see if your organization is exempt from our prohibitions, // please follow the following prompts. // please note that they are not in alphabetical order, and you will have to // give them your full attention. Playback(telemark-polit-choices); // if You represent the America First Party, dial 1. // if You represent the American Party, dial 2. // if You represent the American Heritage Party, dial 3. // if You represent the American Independent Party, dial 4. // if You represent the American Nazi Party, dial 5. // if You represent the Pot Party, dial 6. // if You represent the American Reform Party, dial 7. // if You represent the Christian Falenqist Party of America, dial 8. // all others, please dial 9. } 1 => goto telemarket-poli-Am1st|s|begin; 2 => goto telemarket-poli-American|s|begin; 3 => goto telemarket-poli-AmHer|s|begin; 4 => goto telemarket-poli-AmInd|s|begin; 5 => goto telemarket-poli-AmNaz|s|begin; 6 => goto telemarket-poli-Pot|s|begin; 7 => goto telemarket-poli-AmRef|s|begin; 8 => goto telemarket-poli-CFP|s|begin; 9 => goto telemarket-political2|s|begin; t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemarket-political2 { s => { begin: Playback(telemark-politx-intro); // Thank you for your patience, and I congratulate you for your persistence. // Just a few more options! // Playback(telemark-polit2-choices); // if You represent the Communist Party USA, dial 1. // if You represent the Constitution Party, dial 2. // if You represent the Family Values Party, dial 3. // if You represent the Freedom Socialist Party, dial 4. // if You represent the Grass Roots Party, dial 5. // if You represent the Green Party, dial 6. // if You represent the Greens Party, dial 7. // if You represent the Independence Party, dial 8. // all others, goto 9. } 1 => goto telemarket-poli-Communist|s|begin; 2 => goto telemarket-poli-Constit|s|begin; 3 => goto telemarket-poli-FamVal|s|begin; 4 => goto telemarket-poli-FreedSoc|s|begin; 5 => goto telemarket-poli-Grassroot|s|begin; 6 => goto telemarket-poli-Green|s|begin; 7 => goto telemarket-poli-Greens|s|begin; 8 => goto telemarket-poli-Independence|s|begin; 9 => goto telemarket-political3|s|begin; t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemarket-political3 { s => { begin: Playback(telemark-politx-intro); Playback(telemark-polit3-choices); // if You represent the Independant American Party, dial 1. // if You represent the Labor Party, dial 2. // if You represent the Libertarian Party, dial 3. // if You represent the Light Party, dial 4. // if You represent the Natural Law Party, dial 5. // if You represent the New Party, dial 6. // if You represent the New Union Party, dial 7. // if You represent the Peace and Freedom Party, dial 8. // all others, hang on, dial 9. } 1 => goto telemarket-poli-IndAm|s|begin; 2 => goto telemarket-poli-Labor|s|begin; 3 => goto telemarket-poli-Liber|s|begin; 4 => goto telemarket-poli-Light|s|begin; 5 => goto telemarket-poli-NatLaw|s|begin; 6 => goto telemarket-poli-New|s|begin; 7 => goto telemarket-poli-NewUn|s|begin; 8 => goto telemarket-poli-PeaceFree|s|begin; 9 => goto telemarket-political4|s|begin; t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemarket-political4 { s => { begin: Playback(telemark-politx-intro); Playback(telemark-polit4-choices); // if You represent the Prohibition Party, dial 1. // if You represent the Reform Party, dial 2. // if You represent the Revolution , dial 3. // if You represent the Socialist Party USA, dial 4. // if You represent the Socialist Action Party, dial 5. // if You represent the Socialist Equality Party, dial 6. // if You represent the Socialist Labor Party, dial 7. // if You represent the Socialist Workers Party, dial 8. // all others, hang on, and dial 9. } 1 => goto telemarket-poli-Prohib|s|begin; 2 => goto telemarket-poli-Ref|s|begin; 3 => goto telemarket-poli-Revol|s|begin; 4 => goto telemarket-poli-SocPart|s|begin; 5 => goto telemarket-poli-SocAct|s|begin; 6 => goto telemarket-poli-SocEq|s|begin; 7 => goto telemarket-poli-SocLab|s|begin; 8 => goto telemarket-poli-SocWork|s|begin; 9 => goto telemarket-political5|s|begin; t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemarket-political5 { s => { begin: Playback(telemark-politx-intro); Playback(telemark-polit5-choices); // if You represent the Southern Party, dial 1. // if You represent the Southern Independence Party, dial 2. // if You represent the US Pacifist Party, dial 3. // if You represent the We the People Party, dial 4. // if You represent the Workers World Party, dial 5. // if You represent the Democratic Party, dial 6. // if You represent the Republican Party, dial 7. // all others, may dial 8. } 1 => goto telemarket-poli-South|s|begin; 2 => goto telemarket-poli-SoInd|s|begin; 3 => goto telemarket-poli-USPac|s|begin; 4 => goto telemarket-poli-WTP|s|begin; 5 => goto telemarket-poli-WWP|s|begin; 6 => goto telemarket-poli-Democrat|s|begin; 7 => goto telemarket-poli-Repub|s|begin; 8 => goto telemarket-poli-other|s|begin; t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemarket-poli-other { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Repub { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Democrat { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-WWP { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-WTP { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-USPac { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-SoInd { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-South { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-SocWork { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-SocLab { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-SocEq { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-SocAct { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-SocPart { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Revol { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Ref { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Prohib { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-PeaceFree { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-NewUn { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-New { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-NatLaw { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Light { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Liber { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Labor { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-IndAm { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Independence { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Greens { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Green { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Grassroot { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-FreedSoc { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-FamVal { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Constit { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Communist { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-CFP { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-AmRef { s => { begin: goto telemarket-sorry|s|begin; } } // BAD DESIGN: Putting in infinite loops in the menus, whether by design or mistake is not nice! context telemarket-poli-Pot { s => { begin: goto telemarket-political|s|begin; // will the Pot Party Guys even notice an infinite loop? } } context telemarket-poli-AmNaz { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-AmInd { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-AmHer { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-American { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-poli-Am1st { s => { begin: goto telemarket-sorry|s|begin; } } context telemarket-pollster { s => { begin: Playback(telemark-poll-intro); // I'm sorry-- We are just not available for doing any polling at the moment. So, // please remove us from your list. goto telemarket-sorry|s|begin; } t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemarket-research { s => { begin: Playback(telemark-research-intro); // I'd like to say I'd love to help you with your market survey, but that would be a complete // and total lie. I am not interested in helping you with Market Surveys. // // Please remove me from your call list. It just doesn't pay enough. But Thank you. goto telemarket-sorry|s|begin; } t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemarket-magazine { s => { begin: Playback(telemark-mag-choices); // If you are calling to see if I would like a NEW free subscription // to your magazine or newsletter, please dial 1. // If you are calling to see if I want to Renew an existing subscription, please dial 2. // If you are representing some publisher, and want my opinion about something, or are doing // some kind of survey, please dial 3. // If you are calling to verify that some previous caller actually called me, and the // verification information is correct, please dial 4. // and if your call purpose doesn't match any of the above, please dial 5. } 1 => goto telemark-mag-new|s|begin; 2 => goto telemark-mag-renew|s|begin; 3 => goto telemark-mag-survey|s|begin; 4 => goto telemark-mag-verify|s|begin; 5 => goto telemark-mag-other|s|begin; t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemark-mag-new { s => { begin: Playback(telemark-mag-new); // I'm sorry, I'm maxed out, and the answer is NO. // If you really think I'd LOVE to add your publication to the pile I already get, // Send something via the post. Don't call me. // Thank you. bye. Hangup(); } t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemark-mag-renew { s => { begin: Playback(telemark-mag-renew); // So, you want to see if I want to Renew, do you? The answer is most likely "YES". // // But, I will not answer a long list of questions over the phone. Send such // categorization info via the post, and stop bothering me over the phone, // if this is what you want. // Do you need verification information? Normally I opt out of such nonsense, if possible. // If not, use whatever of the following you can: // My birth month is October. // My birthplace is Kigali, in Rwanda, in Afica. // My eye color is orange. // All of these are wonderfully false, but I use them regularly for such purposes. Thank you. Hangup(); } t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemark-mag-survey { s => { begin: Playback(telemark-mag-survey); // Sorry, I don't have time to answer survey or opinion questions. Find someone // else to help build your marketing database, I guess. Good Luck. Hangup(); } t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemark-mag-verify { s => { begin: Playback(telemark-mag-verify); // If you are calling to verify that your own agents aren't ripping you off, // sorry, I can't help you. I opt out whenever I can, mainly because I'm not // paid enough for this kind of thing. I always lie, and I can't remember // what I might have said. Sorry. Goodbye. Hangup(); } t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemark-mag-other { s => { begin: goto telemarket-sorry|s|begin; } } // BAD DESIGN: Is it entrapment, when you lure telemarketers to reveal their contact information, // Just so you can report them to the FTC/FCC? If it is, isn't it unethical for them // to hide their CID (via Anonymous, usually), to hide their identities from the public? // BTW -- What telemarketer would be stupid enough to fall for this? I'll bet not a single one! // For that matter, what telemarketer will be stupid enough to even enter any of this? I'll bet not a single one! // (but it was fun messing around). context telemarket-commercial { s => { begin: Playback(telemark-comm-intro); // Script: Please leave your name, organization, and phone number, plus // a short description of the purpose of your call, at the prompt. // We will do our best to respond to your call! And, in the mean time, // do not forget to add us to your no-call list! Voicemail(u82); goto telemarket-sorry|s|begin; } t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } context telemarket-other { s => { begin: Playback(telemark-other-intro); // Please review the previous menu options, and see if you really don't // fit in one of the previous categories. // If you do not, go ahead, and call me again, and let me know what category // I should have included in the above list. I appreciate this. Thank you much! Hangup(); } t => goto telemarket|s|begin; i => goto telemarket|s|begin; o => goto telemarket|s|begin; } asterisk-1.6.1.0/pbx/ael/ael-test/ael-test3/include2.ael20000644000175000017500000000014210423206707022065 0ustar maniacmaniac NoOp(This was included from include2.ael2); #include "include3.ael2" #include "include4.ael2" asterisk-1.6.1.0/pbx/ael/ael-test/ael-test3/include1.ael20000644000175000017500000000011610423206707022065 0ustar maniacmaniac NoOp(Hello, this is included from include1.ael2); #include "include2.ael2" asterisk-1.6.1.0/pbx/ael/ael-test/ael-test3/include4.ael20000644000175000017500000000012710423206707022072 0ustar maniacmaniac NoOp(This is include4.ael2! Isn't it cool!?!?!?!); NoOp(4 doesn't include anything); asterisk-1.6.1.0/pbx/ael/ael-test/ael-test3/include3.ael20000644000175000017500000000007110423206707022067 0ustar maniacmaniac NoOp(This is include3.ael2!); #include "include5.ael2" asterisk-1.6.1.0/pbx/ael/ael-test/ael-test3/include5.ael20000644000175000017500000000007010423206707022070 0ustar maniacmaniac NoOp(Include5.ael2 doesn't include anything, either!); asterisk-1.6.1.0/pbx/ael/ael-test/ael-test3/extensions.ael0000755000175000017500000022245210722651651022516 0ustar maniacmaniacglobals { static=yes; writeprotect=yes; CONSOLE=Console/dsp; // Console interface for demo IAXINFO=murf:tlhfckoct; // IAXtel username/password FWDNUMBER=544788 ; // your calling number FWDCIDNAME="Joe-Worker"; // your caller id FWDPASSWORD=zingledoodle ; // your password FWDRINGS=Zap/6 ; // the phone to ring FWDVMBOX=1 ; // the VM box for this user } macro std-exten( ext , dev ) { Dial(${dev}/${ext},20); goto privacyManagerFailed|s|begin; switch(${DIALSTATUS}) { case BUSY: Voicemail(b${ext}); break; case NOANSWER: Voicemail(u${ext}); break; case ANSWER: break; default: Voicemail(u${ext}); } catch a { VoiceMailMain(${ext}); } } macro std-priv-exten_1( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_2( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_3( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_4( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_5( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_6( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_7( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_8( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_9( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_10( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_11( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_12( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_13( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_14( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_15( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_16( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_17( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_18( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_19( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_20( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_21( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_22( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_23( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_24( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_25( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_26( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_27( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_28( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_29( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_30( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_31( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_32( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_33( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_34( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_35( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_36( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_37( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_38( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_39( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_40( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_41( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_42( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_43( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_44( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_45( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_46( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_47( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_48( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_49( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_50( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_51( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_52( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_53( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_54( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_55( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_56( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_57( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_58( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_59( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_60( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_61( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_62( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_63( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_64( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_65( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_66( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_67( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_68( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_69( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_70( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_71( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_72( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten_73( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro std-priv-exten( dev, ext , timeout, opts, torcont, dontcont ) { Dial(${dev},${timeout},${opts}); NoOp(${DIALSTATUS} was chosen); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: Voicemail(b${ext}); break; case ANSWER: break; case NOANSWER: Voicemail(u${ext}); break; default: Voicemail(u${ext}); } } macro fillcidname() { if( "${CALLERID(num)}" = "" ) // nothing to work with, quit!!! return; Set(cidn=${DB(cidname/${CALLERID(num)})}); if( "${CALLERID(name)}" != "" ) { if( ("${cidn}" = "Privacy Manager" & "${CALLERID(name)}" != "Privacy Manager") | "${cidn}" = "" ) // if the entry isn't in the database, // or if an entry exists, and it's "Privacy Manager", empty, (or add other useless possibilities). { Set(DB(cidname/${CALLERID(num)})=${CALLERID(name)}); // then set or override what's in the DB } } // Now, we fill in the callerid info from the incoming entry, if it's stuff worth using // Ignore fundamentally semi-anonymous information from local cell phones // if the db has an entry for this number, and it's not a canned string from a cell phone company if( ( "${cidn}" != "" ) & ( "${CALLERID(name)}" = "" | "${CALLERID(name)}" = "CODY,WY " | "${CALLERID(name)}" = "POWELL,WY " | "${CALLERID(name)}" = "WIRELESS CALLER" | "${CALLERID(name)}" = "SUBSCRIBER,WIRE" | "${CALLERID(name)}" = "CELLULAR ONE" | "${CALLERID(name)}" = "Cellular One Customer" | "${CALLERID(name)}" = "CELLULAR ONE " | "${CALLERID(name)}" = "Privacy Manager" | "${CALLERID(name)}" = "RIVERTON,WY " | "${CALLERID(name)}" = "BASIN,WY " | "${CALLERID(name)}" = "BILLINGS,MT " | "${CALLERID(name)}" = "PROVO,UT " | "${CALLERID(name)}" = "TOLL FREE " ) ) // put stuff in the above, that the phone company tends to put in your callerid, // that you would rather override with DB info // there's no way to guess them all, but you can get the most popular ones... // why cell phones can't do CID like everybody else, ....? { Set(CALLERID(name)=${cidn}); // Override what the phone company provides with what's in the DB for this number. } } macro ciddial(dialnum, lookup, waittime, dialopts, ddev) { Set(cidnu=${CALLERID(num)}); Set(cidn=${DB(cidname/${lookup})}); Set(CALLERID(name)=${cidn}); Dial(${ddev}/${dialnum}|${waittime}|${dialopts}); if( "${DIALSTATUS}" = "CHANUNAVAIL" ) { BackGround(try_voip); CALLERID(num)=7075679201; Dial(SIP/1${lookup}@tctwest,${waittime},${dialopts}); if( "${DIALSTATUS}" = "CHANUNAVAIL" ) { BackGround(try_cell); CALLERID(num)=${cidnu}; // put the original number back Dial(Zap/2/${lookup},${waittime},${dialopts}); } } } macro ciddial3(dialnum, lookup, waittime, dialopts, ddev) { Set(cidnu=${CALLERID(num)}); Set(cidn=${DB(cidname/${lookup})}); Set(CALLERID(name)=${cidn}); Dial(${ddev}/${dialnum}|${waittime}|${dialopts}); if( "${DIALSTATUS}" = "CHANUNAVAIL" ) { BackGround(try_cell); Dial(Zap/2/${lookup},${waittime},${dialopts}); } } macro ciddial2(dialnum, lookup, waittime, dialopts, ddev) // give priority to tctwest, then the ZAP in emergencies { Set(cidn=${DB(cidname/${lookup})}); Set(cidnu=${CALLERID(num)}); Set(CALLERID(name)=${cidn}); Set(CALLERID(num)=7075679201); Dial(SIP/1${lookup}@tctwest,${waittime},${dialopts}); if( "${DIALSTATUS}" = "CHANUNAVAIL" ) { Set(CALLERID(num)=${cidnu}); // put the original number back BackGround(try_zap); Dial(${ddev}/${dialnum},${waittime}|${dialopts}); if( "${DIALSTATUS}" = "CHANUNAVAIL" ) { BackGround(try_cell); Dial(Zap/2/${lookup},${waittime},${dialopts}); } } } macro callerid-liar() { TrySystem(/usr/bin/play /var/lib/asterisk/sounds/priv-callerintros/LIAR.gsm&); Background(priv-liar); // Script: OOOps! Sorry! I don't allow men with ski masks pulled over their // faces to get in the front door, and unidentified callers won't fair // any better. You entered *MY* phone number. That won't work. // If you are telemarketing, cross me off the list, and don't call again. // If you did this by mistake, forgive my defenses, and call again. // Alternate: (priv-liar2) // Script: You have chosen to try to deceive my system and withold your CallerID, // by entering my own phone number as YOUR CallerID. I find this // offensive because you are being dishonest. I will not do business nor // waste my time talking to anyone who is less than honest and forthcoming. // Take me off your call list and do not call me again. Hangup(); } macro callerid-bad() { mycid=${CALLERID(num)}:"1([0-9]+)"; Set(CALLERID(num)=${mycid}); Wait(0); } context privacyManagerFailed { s => { begin: Background(PrivManInstructions); // Script: OOps, that didn't go well. You need to enter *your* area code, and *your* 7 digit // phone number, for a total of 10 digits, or you'll be handed over to the monkeys. Let's // try this again, and hopefully you can get past our front-line defenses! PrivacyManager(); if( "${PRIVACYMGRSTATUS}" = "FAILED" ) { Background(tt-allbusy); Background(tt-somethingwrong); Background(tt-monkeysintro); Background(tt-monkeys); Background(tt-weasels); Hangup(); } else { goto homeline|s|postPriv; } } } // Some comments // Some more comments context homeline { s => { begin: Answer(); Set(repeatcount=0); Zapateller(nocallerid); PrivacyManager(); if( "${PRIVACYMGRSTATUS}" = "FAILED" ) { TrySystem(/usr/bin/play /var/lib/asterisk/sounds/privmanfailed.gsm); &std-priv-exten(Zap/3r1&Zap/5r1,2,25,mtw,telemarket,telemarket); Hangup(); return; // goto privacyManagerFailed|s|begin; } postPriv: &fillcidname(); Set(CONFCIDNA=${CALLERID(name)}); Set(CONFCIDNU=${CALLERID(num)}); AGI(callall); AGI(submit-announce.agi); if( "${CALLERID(num)}" : "1" ) { &callerid-bad(); } if( "${CALLERID(num)}" = "7077577685" & "${CALLERID(name)}" : "Privacy Manager" ) { &callerid-liar(); } TrySystem(/usr/local/bin/who-is-it ${CALLERID(num)} "${CALLERID(name)}"&); Set(lds=${DB(playlds/${CALLERID(num)})}); if( "${lds}" = "1" ) { SetMusicOnHold(mohlds); } direct=${DB(DirectCall/${CALLERID(num)})}; if( "${direct}" != "" & ${direct} != 0 ) { verbose(direct is XXX#${direct}XXXX); Playback(greetings/direct); // Welcome to the Murphy residence. This system will automatically try to connect you to... Playback(/var/spool/asterisk/voicemail/default/${direct}/greet); TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/${direct}/greet.wav&); switch(${direct}) { case 1: //Steve &std-priv-exten(Zap/6r3&Sip/murf,1,25,mpA(beep)tw,telemarket,telemarket); goto s|loopback; case 2: //Sonya &std-priv-exten(Zap/3r1&Zap/5r1,2,25,mtw,telemarket,telemarket); goto s|loopback; default: // all the kids Set(z=${direct}-2); goto homeline-kids|${z}|1; } } loopback: ifTime(*|*|20-25|dec) { Playback(greetings/christmas); } else ifTime(*|*|31|dec) { Playback(greetings/newyear); } else ifTime(*|*|1|jan) { Playback(greetings/newyear); } else ifTime(*|*|14|feb) { Playback(greetings/valentines); } else ifTime(*|*|17|mar) { Playback(greetings/stPat); } else ifTime(*|*|31|oct) { Playback(greetings/halloween); } else ifTime(*|mon|15-21|jan) { Playback(greetings/mlkDay); } else ifTime(*|thu|22-28|nov) { Playback(greetings/thanksgiving); } else ifTime(*|mon|25-31|may) { Playback(greetings/memorial); } else ifTime(*|mon|1-7|sep) { Playback(greetings/labor); } else ifTime(*|mon|15-21|feb) { Playback(greetings/president); } else ifTime(*|sun|8-14|may) { Playback(greetings/mothers); } else ifTime(*|sun|15-21|jun) { Playback(greetings/fathers); } else { Playback(greetings/hello); // None of the above? Just a plain hello will do } Background(murphy-homeline-intro1); // Script: Hello-- Welcome to the Murphy's! If you already know what // option you want, you don't have to wait for this entire spiel-- just // have at it. // If you are calling because this number is on a list of some sort, dial 6. // If you want Sonya, dial 1. // If you want one of the kids, dial 2. // If you want Steve, dial 3. // to play with your introduction, dial 5. // If we don't seem to be giving you the time of day, try 7. // Have a good day! } 1 => { // Sonya TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/2/greet.wav&); &std-priv-exten(Zap/3r1&Zap/5r1,2,25,mtw,telemarket,telemarket); goto s|loopback; } 2 => { // Kids goto homeline-kids|s|begin; } 21 => { Dial(IAX2/seaniax,20,T); } 3 => { // Steve &std-priv-exten(Zap/6r3&Sip/murf,1,25,mpA(beep)tw,telemarket,telemarket); goto s|loopback; } 4 => { // Voicemail VoicemailMain(); goto s|loopback; } 5 => { // play with intro goto home-introduction|s|begin; } 6 => { // Telemarketers goto telemarket|s|begin; } 7 => { // time of day, riddle agi(tts-riddle.agi); Background(gsm/what-time-it-is2); SayUnixTime(); goto s|loopback; } 792 => { // Page All goto pageall|s|begin; } 793 => { // check the tone recognition Read(zz,,0,,1,0); SayDigits(${zz}); } t => { Set(repeatcount=${repeatcount} + 1); if( ${repeatcount} < 3 ) { goto s|loopback; // just loopback isn't enough } Hangup(); } i => { Background(invalid); goto s|loopback; } o => { Congestion(); } fax => { Dial(Zap/4); } } // Some comments // Some more comments context pageall { s => { begin: AGI(callall); MeetMe(5555,dtqp); MeetMeAdmin(5555,K); Hangup(); } h => { begin: MeetMeAdmin(5555,K); Background(conf-muted); Hangup(); } } // Some comments // Some more comments context add-to-conference { start => { NoCDR(); MeetMe(5555,dmqp); } h => { Hangup(); } } context home-introduction { s => { begin: Background(intro-options); // Script: To hear your Introduction, dial 1. // to record a new introduction, dial 2. // to return to the main menu, dial 3. // to hear what this is all about, dial 4. } 1 => { Playback(priv-callerintros/${CALLERID(num)}); goto s|begin; } 2 => { goto home-introduction-record|s|begin; } 3 => { goto homeline|s|loopback; } 4 => { Playback(intro-intro); // Script: // This may seem a little strange, but it really is a neat // thing, both for you and for us. I've taped a short introduction // for many of the folks who normally call us. Using the Caller ID // from each incoming call, the system plays the introduction // for that phone number over a speaker, just as the call comes in. // This helps the folks // here in the house more quickly determine who is calling. // and gets the right ones to gravitate to the phone. // You can listen to, and record a new intro for your phone number // using this menu. goto s|begin; } t => { goto s|begin; } i => { Background(invalid); goto s|begin; } o => { goto s|begin; } } context home-introduction-record { s => { begin: Background(intro-record-choices); // Script: // If you want some advice about recording your // introduction, dial 1. // otherwise, dial 2, and introduce yourself after // the beep. } 1 => { Playback(intro-record); // Your introduction should be short and sweet and crisp. // Your introduction will be limited to 10 seconds. // This is NOT meant to be a voice mail message, so // please, don't say anything about why you are calling. // After we are done making the recording, your introduction // will be saved for playback. // If you are the only person that would call from this number, // please state your name. Otherwise, state your business // or residence name instead. For instance, if you are // friend of the family, say, Olie McPherson, and both // you and your kids might call here a lot, you might // say: "This is the distinguished Olie McPherson Residence!" // If you are the only person calling, you might say this: // "This is the illustrious Kermit McFrog! Pick up the Phone, someone!!" // If you are calling from a business, you might pronounce a more sedate introduction,like, // "Fritz from McDonalds calling.", or perhaps the more original introduction: // "John, from the Park County Morgue. You stab 'em, we slab 'em!". // Just one caution: the kids will hear what you record every time // you call. So watch your language! // I will begin recording after the tone. // When you are done, hit the # key. Gather your thoughts and get // ready. Remember, the # key will end the recording, and play back // your intro. Good Luck, and Thank you!" goto 2|begin; } 2 => { begin: Background(intro-start); // OK, here we go! After the beep, please give your introduction. Background(beep); Record(priv-callerintros/${CALLERID(num)}:gsm,3); Background(priv-callerintros/${CALLERID(num)}); goto home-introduction|s|begin; } t => { goto s|begin; } i => { Background(invalid); goto s|begin; } o => { goto s|begin; } } context homeline-kids { s => { begin: Background(murphy-homeline-kids); // Which Kid? 1=Sean, 2:Eric, 3:Ryan, 4:Kyle, 5:Amber, 6:Alex, 7:Neal } 1 => { // SEAN TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/3/greet.wav&); // &std-priv-exten(Zap/3r2&Zap/5r2,3,35,mtw,telemarket,telemarket); &std-priv-exten(IAX2/seaniax&Zap/5r2,3,35,mtw,telemarket,telemarket); goto homeline|s|loopback; } 2 => { // ERIC TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/4/greet.wav&); Voicemail(u4); goto homeline|s|loopback; // SetMusicOnHold(erics); // TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); // TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/4/greet.wav&); // &std-priv-exten(Zap/3r2&Zap/5r2,4,35,mtw,telemarket,telemarket); // goto homeline|s|loopback; } 3 => { // RYAN TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/5/greet.wav&); &std-priv-exten(Zap/3r2&Zap/5r2,5,35,mtw,telemarket,telemarket); goto homeline|s|loopback; } 4 => { // KYLE TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/6/greet.wav&); &std-priv-exten(Zap/3r2&Zap/5r2,6,35,mtw,telemarket,telemarket); goto homeline|s|loopback; } 5 => { TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/7/greet.wav&); &std-priv-exten(Zap/3r2&Zap/5r2,7,35,mtw,telemarket,telemarket); goto homeline|s|loopback; } 6 => { TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/8/greet.wav&); &std-priv-exten(Zap/3r2&Zap/5r2,8,35,mtw,telemarket,telemarket); goto homeline|s|loopback; } 7 => { TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/9/greet.wav&); &std-priv-exten(Zap/3r2&Zap/5r2,9,35,mtw,telemarket,telemarket); goto homeline|s|loopback; } t => { goto s|begin; } i => { Background(invalid); goto s|begin; } o => { goto s|begin; } } context voipworkline { s => { begin: Answer(); TrySystem(/usr/local/bin/who-is-it ${CALLERID(num)} "${CALLERID(name)}"&); goto workline|s|loopback; } 7075679201 => { Answer(); TrySystem(/usr/local/bin/who-is-it ${CALLERID(num)} "${CALLERID(name)}"&); goto workline|s|loopback; } } context workline { s => { begin: Answer(); Wait(1); Set(repeatcount=0); Zapateller(nocallerid); // PrivacyManager(); // if( "${PRIVACYMGRSTATUS}" = "FAILED" ) // { // goto privacyManagerFailed|s|begin; // } &fillcidname(); TrySystem(/usr/local/bin/who-is-it ${CALLERID(num)} "${CALLERID(name)}"&); loopback: Background(greetings/greeting); //script: Hello Background(murphy-office-intro1); //script: welcome to Steve Murphy's office. If you are dialing // this number because it was on a calling list of any sort, dial 6. // Otherwise, dial 1, and hopefully, you will reach Steve. } 1 => { TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/1/greet.wav&); &std-priv-exten(Zap/6&Sip/murf,1,30,mtw,telemarket,telemarket); goto s|loopback; } 4 => { VoicemailMain(); goto s|loopback; } 6 => { goto telemarket|s|begin; } 793 => { // check the tone recognition Read(zz,,0,,1,0); SayDigits(${zz}); } t => { repeatcount=${repeatcount} + 1; if( ${repeatcount} < 3 ) { goto s|loopback; // just loopback isn't enough } Hangup(); } i => { Background(invalid); goto s|loopback; } o => { Congestion(); } fax => { Answer(); Dial(Zap/4); } } context dialFWD { ignorepat => 8; ignorepat => 9; _83. => { Set(CALLERID(name)=${FWDCIDNAME}); Dial(IAX2/${FWDNUMBER}:${FWDPASSWORD}@iax2.fwdnet.net/${EXTEN:2},60,r); Congestion(); } _82NXX => { Set(CALLERID(name)=${FWDCIDNAME}); Dial(IAX2/${FWDNUMBER}:${FWDPASSWORD}@iax2.fwdnet.net/${EXTEN:2},60,r); Congestion(); } _92NXX => { Set(CALLERID(name)=${FWDCIDNAME}); Dial(IAX2/${FWDNUMBER}:${FWDPASSWORD}@iax2.fwdnet.net/${EXTEN:2},60,r); Congestion(); } } context dialiaxtel { ignorepat => 8; ignorepat => 9; _81700NXXXXXX => { Dial(IAX2/zorch:zilchnoodle@iaxtel.com/${EXTEN:1}@iaxtel); } _81800NXXXXXX => { Dial(IAX2/zorch:zilchnoodle@iaxtel.com/${EXTEN:1}@iaxtel); } _91700NXXXXXX => { Dial(IAX2/zorch:zilchnoodle@iaxtel.com/${EXTEN:1}@iaxtel); } _91800NXXXXXX => { Dial(IAX2/zorch:zilchnoodle@iaxtel.com/${EXTEN:1}@iaxtel); } } context dialgoiax { ignorepat => 9; _93. => { Set(CALLERID(name)="Joe Worker"); Dial(IAX2/878201007658:stickyfinger295@server1.goiax.com/${EXTEN:2},60,r); Congestion(); } } context homefirst { ignorepat => 9; _91NXXNXXXXXX => { &ciddial(${EXTEN:1},${EXTEN:2},30,TW,Zap/1); } _9754XXXX => { &ciddial(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9574XXXX => { &ciddial(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9202XXXX => { &ciddial(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9219XXXX => { &ciddial(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9254XXXX => { &ciddial(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9716XXXX => { &ciddial(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9NXXXXXX => { &ciddial(1707${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9011. => { &ciddial(${EXTEN:1},${EXTEN:1},30,TW,Zap/1); } _9911 => { Dial(Zap/1/911,30,T); } _9411 => { Dial(Zap/1/411,30,T); } } context workfirst { ignorepat => 9; _91NXXNXXXXXX => { &ciddial2(${EXTEN:1},${EXTEN:2},30,TW,Zap/1); } _9754XXXX => { &ciddial2(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9574XXXX => { &ciddial2(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9202XXXX => { &ciddial2(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9219XXXX => { &ciddial2(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9254XXXX => { &ciddial2(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9716XXXX => { &ciddial2(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9NXXXXXX => { &ciddial2(1707${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); } _9911 => { Dial(Zap/1/911,30,T); } _9411 => { Dial(Zap/1/411,30,T); } } context force_cell { ignorepat => 8; _81NXXNXXXXXX => { &ciddial(${EXTEN:1}#,${EXTEN:2},30,TW,Zap/2); } _8754XXXX => { &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); } _8574XXXX => { &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); } _8202XXXX => { &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); } _8219XXXX => { &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); } _8254XXXX => { &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); } _8716XXXX => { &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); } _8NXXXXXX => { &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); } _8911 => { Dial(Zap/1/911|30|T); } _8411 => { Dial(Zap/1/411|30|T); } } context force_home { ignorepat => 8; _81NXXNXXXXXX => { &ciddial3(${EXTEN:1}#,${EXTEN:2},30,TW,Zap/1); } _8754XXXX => { &ciddial3(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); } _8574XXXX => { &ciddial3(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); } _8202XXXX => { &ciddial3(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); } _8219XXXX => { &ciddial3(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); } _8254XXXX => { &ciddial3(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); } _8716XXXX => { &ciddial3(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); } _8NXXXXXX => { &ciddial3(1707${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); } _8911 => { Dial(Zap/1/911|30|T); } _8411 => { Dial(Zap/1/411|30|T); } } context homeext { ignorepat => 8; ignorepat => 9; includes { parkedcalls; homefirst; force_cell; } s => { loopback: Wait(0); } 1 => { &std-priv-exten(Zap/3&Zap/5,2,35,mtw,telemarket,telemarket); goto s|loopback; } 2 => { &std-priv-exten(Zap/6&Zap/5,1,35,mpA(beep3)Tt,telemarket,telemarket); goto s|loopback; } 4 => { VoicemailMain(); } 5 => { Record(recording:gsm); Background(recording); } 6 => { Background(recording); } 760 => { DateTime(); goto s|loopback; } 761 => { Record(announcement:gsm); TrySystem(/usr/bin/play /var/lib/asterisk/sounds/announcement.gsm&); goto s|loopback; } 762 => { agi(tts-riddle.agi); Background(gsm/what-time-it-is2); SayUnixTime(); goto s|loopback; } 763 => { Set(CALLERID(num)=); Dial(Zap/6r3,35,mptA(beep3)); //results: it should ALWAYS ask for an intro; the intro should not be left behind Hangup(); } 764 => { Set(CALLERID(num)=); Dial(Zap/6r3,35,mptnA(beep3)); //results: Don't save the intro; shouldn't anyway if no callerid Hangup(); } 765 => { Set(CALLERID(num)=); Dial(Zap/6r3,35,mptNA(beep3)); //results: Don't screen if there's CALLERID; it should screen the call. Hangup(); } 766 => { Dial(Zap/6r3,35,mptNA(beep3)); //results: Don't screen if there's CALLERID; it should screen the call. Hangup(); } 767 => { Dial(Zap/6r3,35,mptnA(beep3)); //results: Don't save the intro; the interesting case, because callerID should be present. Hangup(); } 769 => { Playtones(dial); Wait(2); Playtones(busy); Wait(2); Playtones(ring); Wait(2); Playtones(congestion); Wait(2); Playtones(callwaiting); Wait(2); Playtones(dialrecall); Wait(2); Playtones(record); Wait(2); Playtones(info); Wait(5); Hangup(); } 790 => { MeetMe(790,p); } 792 => { goto pageall|s|begin; } 795 => { AGI(wakeup.agi);Congestion(); } 544716 => { // Incoming call from FWD TrySystem(/usr/local/bin/who-is-it ${CALLERID(num)} "${CALLERID(name)}"&); goto s|loopback; } i => { Background(invalid); goto s|loopback; } o => { goto s|loopback; } t => { Congestion(); } } context fromvmhome { 1 => { Dial(Zap/6&Sip/murf|20|Tt); } 2 => { Dial(Zap/3&Zap/5|20|Tt); } _707202XXXX => { &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707219XXXX => { &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707254XXXX => { &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707716XXXX => { &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707754XXXX => { &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707574XXXX => { &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); } _NXXNXXXXXX => { &ciddial(1${EXTEN},${EXTEN},30,TW,Zap/1); } _1NXXNXXXXXX => { // HAND DIALING &ciddial(${EXTEN},${EXTEN:1},30,TW,Zap/1); } _754XXXX => { &ciddial(${EXTEN},707${EXTEN},30,TW,Zap/1); } _574XXXX => { &ciddial(${EXTEN},707${EXTEN},30,TW,Zap/1); } _NXXXXXX => { &ciddial(1707${EXTEN},707${EXTEN},30,TW,Zap/1); } _911 => { &ciddial(911,911,30,TW,Zap/1); } _411 => { &ciddial(411,411,30,TW,Zap/1); } } context fromvmwork { 1 => { Dial(Zap/6&Sip/murf|20|Tt); } 2 => { Dial(Zap/3&Zap/5|20|Tt); } _707202XXXX => { &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707219XXXX => { &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707254XXXX => { &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707716XXXX => { &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707754XXXX => { &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707574XXXX => { &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); } _NXXNXXXXXX => { &ciddial(1${EXTEN},${EXTEN},30,TW,Zap/1); } _1NXXNXXXXXX => { // HAND DIALING &ciddial(${EXTEN},${EXTEN:1},30,TW,Zap/1); } _754XXXX => { &ciddial(${EXTEN},707${EXTEN},30,TW,Zap/1); } _574XXXX => { &ciddial(${EXTEN},707${EXTEN},30,TW,Zap/1); } _NXXXXXX => { &ciddial(1707${EXTEN},707${EXTEN},30,TW,Zap/1); } 911 => { &ciddial(911,911,30,TW,Zap/1); } 411 => { &ciddial(411,411,30,TW,Zap/1); } } context fromSeanUniden { includes { parkedcalls; } 21 => { Dial(IAX2/seaniax,20,T); } _707202XXXX => { &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707219XXXX => { &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707254XXXX => { &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707716XXXX => { &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707754XXXX => { &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); } _707574XXXX => { &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); } _NXXNXXXXXX => { &ciddial(1${EXTEN},${EXTEN},30,TW,Zap/1); } _1NXXNXXXXXX => { &ciddial(${EXTEN},${EXTEN:1},30,TW,Zap/1); } _754XXXX => { &ciddial(${EXTEN},707${EXTEN},30,TW,Zap/1); } _574XXXX => { &ciddial(${EXTEN},707${EXTEN},30,TW,Zap/1); } _NXXXXXX => { &ciddial(1707${EXTEN},707${EXTEN},30,TW,Zap/1); } 911 => { &ciddial(911,911,30,TW,Zap/1); } 411 => { &ciddial(411,411,30,TW,Zap/1); } } context workext { ignorepat => 8; ignorepat => 9; includes { parkedcalls; workfirst; force_home; dialFWD; dialiaxtel; dialgoiax; } s => { loopback: Wait(0); } 1 => { Dial(Zap/3&Zap/5,20,tT); } 2 => { Dial(Zap/5&Zap/6,20,tT); } 21 => { Dial(IAX2/seaniax,20,T); } 22 => { Set(CALLERID(num)=1234567890); Set(CALLERID(name)=TestCaller); Dial(Zap/5,20,mP()A(beep)tw); NoOp(here is dialstatus: ${DIALSTATUS}...); goto s|loopback; } 4 => { VoicemailMain(); goto s|loopback; } 5 => { Record(recording:gsm); Background(recording); } 6 => { ZapBarge(); } 760 => { DateTime(); goto s|loopback; } 761 => { ZapBarge(); goto s|loopback; } 765 => { Playback(demo-echotest); Echo(); Playback(demo-echodone); goto s|loopback; } 766 => { Festival(The other thing to watch is neuro-electronics: the ability to interface technology with our neural system: My wife: Sigrid: has had a cochlear implant since 1996. This once profoundly deaf person now uses the phone: recognizes accents: and listens to movies and recorded books.); goto s|loopback; } 767 => { agi(tts-riddle.agi); Background(gsm/what-time-it-is2); SayUnixTime(); goto s|loopback; } 768 => { agi(tts-computer.agi); } 771 => { eagi(eagi-test); agi(my-agi-test); } 772 => { agi(wakeup.agi); } 775 => { if( ${EXTEN}=${EXTEN} ) { BackGround(digits/1); } else { BackGround(digits/0); } if( ${EXTEN}=${LANGUAGE} ) { BackGround(digits/1); } else { BackGround(digits/0); } BackGround(digits/2); } 776 => { Set(TEST=00359889811777); if( ${TEST}= 00359889811777 ) { BackGround(digits/1); } else { BackGround(digits/0); } if( ${TEST}= 00359889811888 ) { BackGround(digits/1); } else { BackGround(digits/0); } Hangup(); } 790 => { MeetMe(790,p); } 792 => { goto pageall|s|begin; } 793 => { #include "include1.ael2" } 795 => { AGI(wakeup.agi); Congestion(); } 797 => { Set(CONFCIDNA=${CALLERID(name)}); Set(CONFCIDNU=${CALLERID(num)}); AGI(callall); AGI(submit-announce.agi); Hangup(); } } context wakeup { 3 => { Dial(Zap/3|30); } 4 => { Dial(Zap/4|30); } 5 => { Dial(Zap/5|30); } 6 => { Dial(Zap/6|30); } 99 => { Dial(IAX2/murfiaxphone|30); } 97 => { Dial(IAX2/ryaniax|30); } 94 => { Dial(IAX2/seaniax|30); } } context announce-all { s => { begin: MeetMe(5555,dtqp); MeetMeAdmin(5555,K); Hangup(); } h => { MeetMeAdmin(5555,K); Hangup(); } } // now include the telemarketer torture scripts! #include "telemarket_torture.ael2" asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-test10000644000175000017500000000410311021264016020300 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:115 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:pbx_ael.c line:128 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 2-16: The macro testdial does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 18-25: The macro exten-gen does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:1362 func: check_goto Warning: file ./extensions.ael, line 21-21: It's bad form to have a goto in a macro to a target outside the macro! LOG: lev:3 file:pval.c line:1362 func: check_goto Warning: file ./extensions.ael, line 23-23: It's bad form to have a goto in a macro to a target outside the macro! LOG: lev:3 file:pval.c line:2284 func: check_switch_expr Warning: file ./extensions.ael, line 58-58: A default case was automatically added to the switch. LOG: lev:3 file:pval.c line:922 func: check_dow Warning: file ./extensions.ael, line 67-67: The day (m0n) must be one of 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', or 'sat'! LOG: lev:3 file:pval.c line:880 func: check_timerange Warning: file ./extensions.ael, line 78-78: The end time (25:00) is out of range! LOG: lev:2 file:pbx_ael.c line:131 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:134 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:139 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:142 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. LOG: lev:4 file:ael2_parse line:518 func: main 5 contexts, 16 extensions, 159 priorities asterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest12/0000755000175000017500000000000011175405520020053 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-ntest12/extensions.ael0000644000175000017500000000041310463722604022737 0ustar maniacmaniaccontext test1 { 771 => { for( i=0; ${i} <= 3; i = ${i} + 1 ) NoOp(i is '${i}'); } 772 => { for(i=0; ${i} <= 3;i= ${i} + 1 ) NoOp(i is '${i}'); } } asterisk-1.6.1.0/pbx/ael/ael-test/ael-test8/0000755000175000017500000000000011175405520017622 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-test8/extensions.ael0000644000175000017500000000145410445343530022511 0ustar maniacmaniaccontext default { 706/3077610011 => { JabberStatus(asterisk|jmls@mike,StatusCode); switch(${StatusCode}) { case 1: Dial(SIP/706,12); switch(${DIALSTATUS}) { case BUSY: Voicemail(b706); break; default: Voicemail(u706); }; BackGround(hello); break; default: Voicemail(u706); }; Hangup(); }; } asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-test40000644000175000017500000001100310723063404020306 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:113 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:ael.flex line:662 func: setup_filestack --Read in included file ././apptest.ael2, 3474 chars LOG: lev:3 file:ael.y line:546 func: ael_yyparse ==== File: ././apptest.ael2, Line 46, Cols: 8-11: Suggestion: Use the goto statement instead of the Goto() application call in AEL. LOG: lev:2 file:pbx_ael.c line:126 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 35-35: application call to EndWhile affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 37-37: application call to ExecIf affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 38-38: application call to ExecIfTime affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 44-44: application call to Gosub affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 45-45: application call to GosubIf affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:1346 func: check_goto Warning: file ././apptest.ael2, line 46-46: goto: Couldn't find goto target cont|exten|prior, not even in extensions.conf! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 47-47: application call to GotoIf affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 48-48: application call to GotoIfTime affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 58-58: application call to Macro affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2512 func: check_pval_item Warning: file ././apptest.ael2, line 59-59: I am converting the MacroExit call here to a return statement. LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 60-60: application call to MacroIf affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 85-85: application call to Random affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 94-94: application call to Return affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 119-119: application call to StackPop affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:3 file:pval.c line:2507 func: check_pval_item Warning: file ././apptest.ael2, line 141-141: application call to While affects flow of control, and needs to be re-written using AEL if, while, goto, etc. keywords instead! LOG: lev:2 file:pbx_ael.c line:129 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:131 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:134 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:137 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. LOG: lev:4 file:ael2_parse line:531 func: main 1 contexts, 1 extensions, 142 priorities asterisk-1.6.1.0/pbx/ael/ael-test/ael-test2/0000755000175000017500000000000011175405520017614 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-test2/apptest.ael20000644000175000017500000000662210423206707022050 0ustar maniacmaniac// this is a quick test to see how many of the apps we can spot j options in // include this in a macro or extension // at this moment, there are 18 apps that accept the j option. AddQueueMember(zork,iface,20,j); ADSIProg(sfile); AgentCallbackLogin(agent,s,30@cont); AgentLogin(agent,s); AgentMonitorOutgoing(dcn); AGI(whatever); AlarmReceiver(); Answer(2); AppendCDRUserField(value); Authenticate(pword,adjmr); BackGround(filename,snm,eng); BackgroundDetect(filename,20,2,10); Busy(10); ChangeMonitor(fnamebase); ChanIsAvail(Zap/5,sj); ChanSpy(prefix,bg()qrv); Congestion(5); ControlPlayback(filename,10,6,4,0,5,7,j); DateTime(unixtime,tz,fmt); DBdel(fam/key); DBdeltree(fam); DeadAGI(command); Dial(zap/1,45,A()CdD()fgG()hHjL()m()M()nNoprS()tTwW); Dictate(basedir); Directory(cont,dcont,f); DISA(68986869876,context); DumpChan(verblev); DUNDiLookup(90709780978,context,bj); EAGI(command); Echo(); EndWhile(); Exec(appname,args); ExecIf(expr,app,data); ExecIfTime(*,*,*,*,appname); ExternalIVR(command,arg1); Festival(text); Flash(); ForkCDR(v); GetCPEID(); Gosub(cont,exten,priority); GosubIf(cond?label); Goto(cont,exten,prior); GotoIf(cond?t:f); GotoIfTime(*,*,*,*?cont,ext,prior); Hangup(); HasNewVoicemail(vmbox,var,j); HasVoicemail(vmbox,var,j); IAX2Provision(template); ICES(xmlconfig); ImportVar(nevar@chann,var); Log(NOTICE,message); LookupBlacklist(j); LookupCIDName(); Macro(macro,arg1); MacroExit(); MacroIf(expr?etc); MailboxExists(mbox@cont,j); Math(v,2+2); MeetMe(5555,aAbcdDeimMpPqrstTovwxX); MeetMeAdmin(5555,e,user); MeetMeCount(5555,var); Milliwatt(); MixMonitor(filename,abv()V()W(),command); Monitor(file.fmt,base,mb); MP3Player(location); MusicOnHold(class); NBScat(); NoCDR(); NoOp(ignored); Page(Zap/1,dq); Park(exten); ParkAndAnnounce(template,5,238,retcont); ParkedCall(exten); PauseQueueMember(queue,zap,j); Pickup(ext@cont); Playback(file,j); PlayTones(arg); PrivacyManager(3,4,j); Progress(); Queue(queuename,dhHnrtTwW,http://www.where.what,over,5); Random(30,cont,ext,pri); Read(var,fname,10,skip,2,5); ReadFile(var=file,10); RealTime(fam,2,val,prefix); RealTimeUpdate(fam,2,val,2,newval); Record(file,2,10,anqst); RemoveQueueMember(queuename,iface,j); ResetCDR(wav); RetryDial(annound,4,2); Return(); Ringing(); RxFAX(fname,caller); SayAlpha(string); SayDigits(string); SayNumber(digits); SayPhonetic(string); SayUnixTime(unixtime,tz,fmt); SendDTMF(digits,10); SendImage(filename); SendText(text,j); SendURL(URL); Set(a=b); SetAMAFlags(); SetCallerID(clid,a); SetCallerPres(allowed_passed_screen); SetCDRUserField(value); SetGlobalVar(var=val); SetMusicOnHold(class); SetTransferCapability(SPEECH); SIPAddHeader(header); SIPDtmfMode(inband,info,rfc); SIPGetHeader(var@headername); SMS(name); SoftHangup(zap/1,a); StackPop(); StartMusicOnHold(class); StopMonitor(); StopMusicOnHold(); StopPlayTones(); System(command); TestClient(testid); TestServer(); Transfer(zap/1,j); TrySystem(command); TxFAX(filename,caller,debug); UnpauseQueueMember(queuename,iface,j); UserEvent(eventanme,body); Verbose(5,message); VMAuthenticate(mailbox@cont,s); VoiceMail(mailbox@cont,bg()suj); VoiceMailMain(mailbox@cont,pg()s); Wait(2); WaitExten(3,m()); WaitForRing(2); WaitForSilence(2,y); WaitMusicOnHold(2); While(expr); Zapateller(answer,5); ZapBarge(channel); ZapRAS(arg); ZapScan(group); ZapSendKeypadFacility(); asterisk-1.6.1.0/pbx/ael/ael-test/ael-test2/extensions.ael0000644000175000017500000000007310423206707022477 0ustar maniacmaniaccontext test1 { s => { #include "apptest.ael2"; } } asterisk-1.6.1.0/pbx/ael/ael-test/ael-test14/0000755000175000017500000000000011175405520017677 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-test14/extensions.ael0000644000175000017500000000034110473660407022566 0ustar maniacmaniaccontext test1 { 10 => { // nothing but a comment! } 11 => { switch(${somevar}) { case somecase: // nothing but a comment! break; case somecase: // nothing but a comment! continue; } break; } } asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-vtest210000644000175000017500000000026611021264016020556 0ustar maniacmaniac[globals] AXLHAFT=wow-to-the-tenth-power JibberWorthy=zinger3 OFFICE_CODE=503 [from-enum] exten => _${OFFICE_CODE}XXXX,1,Answer() exten => _${OFFICE_CODE}XXXX,2,Goto(${EXTEN:3},1) asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-test30000644000175000017500000004016711021264016020314 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:115 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:ael.flex line:672 func: setup_filestack --Read in included file ././include1.ael2, 78 chars LOG: lev:2 file:ael.flex line:672 func: setup_filestack --Read in included file ././include2.ael2, 98 chars LOG: lev:2 file:ael.flex line:672 func: setup_filestack --Read in included file ././include3.ael2, 57 chars LOG: lev:2 file:ael.flex line:672 func: setup_filestack --Read in included file ././include5.ael2, 56 chars LOG: lev:2 file:ael.flex line:672 func: setup_filestack --Read in included file ././include4.ael2, 87 chars LOG: lev:2 file:ael.flex line:672 func: setup_filestack --Read in included file ././telemarket_torture.ael2, 28036 chars LOG: lev:2 file:pbx_ael.c line:128 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 14-34: The macro std-exten does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:1362 func: check_goto Warning: file ./extensions.ael, line 17-17: It's bad form to have a goto in a macro to a target outside the macro! LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 36-59: The macro std-priv-exten_1 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 62-85: The macro std-priv-exten_2 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 88-111: The macro std-priv-exten_3 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 114-137: The macro std-priv-exten_4 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 140-163: The macro std-priv-exten_5 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 166-189: The macro std-priv-exten_6 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 192-215: The macro std-priv-exten_7 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 218-241: The macro std-priv-exten_8 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 244-267: The macro std-priv-exten_9 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 270-293: The macro std-priv-exten_10 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 296-319: The macro std-priv-exten_11 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 322-345: The macro std-priv-exten_12 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 348-371: The macro std-priv-exten_13 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 374-397: The macro std-priv-exten_14 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 400-423: The macro std-priv-exten_15 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 426-449: The macro std-priv-exten_16 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 452-475: The macro std-priv-exten_17 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 478-501: The macro std-priv-exten_18 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 504-527: The macro std-priv-exten_19 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 530-553: The macro std-priv-exten_20 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 556-579: The macro std-priv-exten_21 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 582-605: The macro std-priv-exten_22 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 608-631: The macro std-priv-exten_23 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 634-657: The macro std-priv-exten_24 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 660-683: The macro std-priv-exten_25 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 686-709: The macro std-priv-exten_26 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 712-735: The macro std-priv-exten_27 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 738-761: The macro std-priv-exten_28 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 764-787: The macro std-priv-exten_29 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 790-813: The macro std-priv-exten_30 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 816-839: The macro std-priv-exten_31 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 842-865: The macro std-priv-exten_32 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 868-891: The macro std-priv-exten_33 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 894-917: The macro std-priv-exten_34 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 920-943: The macro std-priv-exten_35 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 946-969: The macro std-priv-exten_36 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 972-995: The macro std-priv-exten_37 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 998-1021: The macro std-priv-exten_38 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1024-1047: The macro std-priv-exten_39 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1050-1073: The macro std-priv-exten_40 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1076-1099: The macro std-priv-exten_41 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1102-1125: The macro std-priv-exten_42 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1128-1151: The macro std-priv-exten_43 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1154-1177: The macro std-priv-exten_44 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1180-1203: The macro std-priv-exten_45 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1206-1229: The macro std-priv-exten_46 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1232-1255: The macro std-priv-exten_47 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1258-1281: The macro std-priv-exten_48 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1284-1307: The macro std-priv-exten_49 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1310-1333: The macro std-priv-exten_50 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1336-1359: The macro std-priv-exten_51 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1362-1385: The macro std-priv-exten_52 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1388-1411: The macro std-priv-exten_53 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1414-1437: The macro std-priv-exten_54 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1440-1463: The macro std-priv-exten_55 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1466-1489: The macro std-priv-exten_56 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1492-1515: The macro std-priv-exten_57 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1518-1541: The macro std-priv-exten_58 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1544-1567: The macro std-priv-exten_59 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1570-1593: The macro std-priv-exten_60 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1596-1619: The macro std-priv-exten_61 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1622-1645: The macro std-priv-exten_62 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1648-1671: The macro std-priv-exten_63 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1674-1697: The macro std-priv-exten_64 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1700-1723: The macro std-priv-exten_65 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1726-1749: The macro std-priv-exten_66 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1752-1775: The macro std-priv-exten_67 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1778-1801: The macro std-priv-exten_68 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1804-1827: The macro std-priv-exten_69 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1830-1853: The macro std-priv-exten_70 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1856-1879: The macro std-priv-exten_71 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1882-1905: The macro std-priv-exten_72 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1908-1931: The macro std-priv-exten_73 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1934-1957: The macro std-priv-exten does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1959-1995: The macro fillcidname does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 1997-2015: The macro ciddial does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 2017-2028: The macro ciddial3 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 2030-2048: The macro ciddial2 does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 2050-2065: The macro callerid-liar does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 2067-2072: The macro callerid-bad does not end with a return; I will insert one. LOG: lev:2 file:pbx_ael.c line:131 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:134 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:139 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. LOG: lev:2 file:pbx_ael.c line:142 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. LOG: lev:4 file:ael2_parse line:518 func: main 172 contexts, 934 extensions, 2558 priorities asterisk-1.6.1.0/pbx/ael/ael-test/ref.ael-test70000644000175000017500000000507410723063404020324 0ustar maniacmaniac (If you find progress and other non-error messages irritating, you can use -q to suppress them) (You can use the -w option to dump extensions.conf format to extensions.conf.aeldump) LOG: lev:2 file:pbx_ael.c line:113 func: pbx_load_module Starting AEL load process. LOG: lev:2 file:pbx_ael.c line:126 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 22-42: The macro stdexten does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 44-49: The macro announce_minutes does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 59-89: The macro checkanddial does not end with a return; I will insert one. LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 91-100: The macro trunkdial does not end with a return; I will insert one. LOG: lev:4 file:pval.c line:2468 func: check_pval_item Error: file ./extensions.ael, line 98-98: The macro call to checkanddial has 5 arguments, but the macro definition has 7 arguments LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 102-112: The macro checklocal does not end with a return; I will insert one. LOG: lev:4 file:pval.c line:2468 func: check_pval_item Error: file ./extensions.ael, line 107-107: The macro call to checkanddial has 5 arguments, but the macro definition has 7 arguments LOG: lev:3 file:pval.c line:671 func: check_macro_returns Warning: file ./extensions.ael, line 114-119: The macro autodial does not end with a return; I will insert one. LOG: lev:4 file:pval.c line:2468 func: check_pval_item Error: file ./extensions.ael, line 284-284: The macro call to checkanddial has 5 arguments, but the macro definition has 7 arguments LOG: lev:4 file:pval.c line:2468 func: check_pval_item Error: file ./extensions.ael, line 287-287: The macro call to checkanddial has 5 arguments, but the macro definition has 7 arguments LOG: lev:3 file:pval.c line:2426 func: check_pval_item Warning: file ./extensions.ael, line 452-452: macro call to non-existent std-exten-ael! (Not even in the extensions.conf stuff!) LOG: lev:4 file:pbx_ael.c line:139 func: pbx_load_module Sorry, but 0 syntax errors and 4 semantic errors were detected. It doesn't make sense to compile. LOG: lev:4 file:ael2_parse line:531 func: main 0 contexts, 0 extensions, 0 priorities asterisk-1.6.1.0/pbx/ael/ael-test/ael-test19/0000755000175000017500000000000011175405520017704 5ustar maniacmaniacasterisk-1.6.1.0/pbx/ael/ael-test/ael-test19/extensions.ael0000644000175000017500000002177310722651651022605 0ustar maniacmaniaccontext dialextens { /* 101 thru 123, 149 thru 152 */ _10X => Dial(Zap/${EXTEN:2},30,Ttw); _1ZX => Dial(Zap/${EXTEN:1},30,Ttw); } /* Due to extenal wiring: dialing 125 will ring 101 dialing 126 will ring 102 and so on until dialing 147 will ring 123 We can dial out on zap 69 thru 72; and 25-47 */ context dialthrus { /* 369-372; 325-347 */ _3XX => Dial(Zap/${EXTEN:1},30,Ttw); } context t1incoming { includes { dialextens; parkedcalls; } s => { Answer(); Background(welcome-to-test-machine); } } context t1extension { includes { dialextens; dialthrus; } } context incoming { includes { dialextens; parkedcalls; } s => { Answer(); Background(welcome-to-test-machine); } } context incoming { s => { Answer(); } } macro std-priv-exten( dev, ext , timeout, opts, torcont, dontcont ) { // &increment_chosecount(); dial_again: Dial(${dev},${timeout},${opts}); switch(${DIALSTATUS}) { case TORTURE: goto ${torcont}|s|begin; break; case DONTCALL: goto ${dontcont}|s|begin; break; case BUSY: label_busy: Read(reply|work-exten-busy|1||2|15); if ("${reply}"=="") goto label_busy; // infinite loop if Read has probs!! switch(${reply}) { case 1: Set(time1=${EPOCH}); label_redial: WaitMusicOnHold(5); Dial(${dev},${timeout},${opts}); switch(${DIALSTATUS}) { case BUSY: if(${EPOCH}-${time1} >= 20) goto label_busy; goto label_redial; default: return;// goto work_line|s|loopback; } break; case 2: Voicemail(${ext}|b); break; case 3: return; // goto work_line|s|loopback; default: Background(invalid); goto label_busy; } break; case ANSWER: break; case NOANSWER: noanswer_label: Read(reply|work-exten-noanswer|1|skip|2|15); switch(${reply}) { case 1: switch(${ext}) { case 10: Background(no-cell); break; case 11: // &ciddial(2729495,3072729495,30,tw,${GRAMS_TELCO},${WORK_TELCO}); break; case 12: // &ciddial(2725560,3072725560,30,tw,${GRAMS_TELCO},${WORK_TELCO}); break; case 13: // &ciddial(2720197,3072720197,30,tw,${GRAMS_TELCO},${WORK_TELCO}); break; case 14: // &ciddial(2501174,3072501174,30,tw,${GRAMS_TELCO},${WORK_TELCO}); break; case 15: Background(no-cell); break; case 16: Background(no-cell); break; default: Background(invalid); break; } goto noanswer_label; break; case 2: Voicemail(${ext}|u); break; case 3: return; // goto work_line|s|loopback; default: Background(invalid); goto noanswer_label; } Voicemail(${ext}|u); break; default: Voicemail(${ext}|u); } } /* Putting these 3 funcs in extensions.conf! macro funcC(a,b) { Set(Key=); menu: Read(Key,main-menu,1,n,1,5); if("${Key}" = "2") goto y,lab1; catch y { lab1: &funcB(${a},${b}); } } macro funcB(a,b) { Set(Key=); menu: Read(Key,tt-monkeys,1,n,1,5); if("${Key}" = "2") goto z,lab2; catch z { lab2: &funcC(${a},${b}); } } macro funcA() { &funcB(1,2); } */ context extension { includes { dialextens; dialthrus; parkedcalls; } 5 => { Record(recording:wav); Background(recording); } 81 => { iterations=1000000; Set(time1=${EPOCH}); for(i=1; ${i}<${iterations}; i=${i}+1) { NoOp(Hello); } Set(time2=${EPOCH}); Verbose(The time diff is $[${time2} - ${time1} ] seconds); Verbose(Which means that the priorities/sec = $[4* ${iterations} / (${time2} - ${time1}) ]); SayNumber($[4 * ${iterations} / (${time2} - ${time1}) ]); } 82 => { &ndeep(100000); Verbose(Finished 100000 levels deep call!); } 83 => { switch (${EXTEN}) { pattern 8X: Verbose(do something to prepare it); pattern 9X: Verbose(handle both 1xx and 2xx calls); pattern [4-7]X: Verbose(and this too!); } Set(junky=${RAND(0|99999)}); Verbose(Here is a random number: ${junky}.); } 84 => { agi(agi://192.168.134.252/|hello|goodbye|whatever|whoknows,hell2,hello3); } 85 => { &std-priv-exten( Zap/50, 150 , 25, mtw, torcont, dontcont ); } 86 => { Verbose(The version is: ${VERSION()} ); Verbose(The versionnum is: ${VERSION(ASTERISK_VERSION_NUM)} ); Verbose(The user is: ${VERSION(BUILD_USER)} ); Verbose(The hostname is: ${VERSION(BUILD_HOSTNAME)} ); Verbose(The machine is: ${VERSION(BUILD_MACHINE)} ); Verbose(The OS is: ${VERSION(BUILD_OS)} ); Verbose(The date is: ${VERSION(BUILD_DATE)} ); Verbose(The kernel is: ${VERSION(BUILD_KERNEL)} ); Set(vinf=${VERSION()}); Set(vrand=${RAND()}); if( ${ISNULL(${vinf})} ) { if( ${ISNULL(${vrand})} ) Verbose(Version 1.2 or earlier); else Verbose(Version 1.4!!!); } else Verbose(${vinf} indicates version pre-1.6 or higher); } 871 => { NoOp( 1 1 1 1 1 1 1); NoOp( 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6); NoOp(012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678890123456789012345678901234567890); NoOp(${EXTEN:1:2} ${EXTEN} ${EXTEN:1} 1 1 1 1 1 1 1); &dialoutpstn(${TDIRECTCALL-PST}/0${EXTEN},${E${CALLERID(num)}-OPT},${TDIRECTCALL-CID},${TDIRECTCALL-MAX},RotaPadrao) ; } 872 => { Set(ChannelOnly=${CUT(CHANNEL||1)}); Verbose(ChannelOnly=${ChannelOnly}; neat huh?); Set(ChannelOnly=${CUT(CHANNEL,,1)}); Verbose(ChannelOnly=${ChannelOnly}; neat huh?); } 873 => { NOOP(this is a forkcdr test); Set(CALLERID(num)=1234567890); Set(CALLERID(name)=before fork); Forkcdr(v); Set(CALLERID(num)=0987654321); Set(CALLERID(name)=after fork); Answer(); Echo(); Hangup(); } 874 => { SayDigits(307-754-5675); SayPhoneNumber(307-754-5675); SayDigits(--); SayPhoneNumber(123-456-7890); SayDigits(++); SayPhoneNumber(307-754-4454); } 875 => { &funcA(); &funcD(); } 876 => { NoOp(Query resultid ${connid} SELECT var1\, var2 FROM did); NoOp($["Query resultid ${connid} SELECT var1\, var2 FROM did"]); NoOp($["Query resultid ${connid} SELECT var1, var2 FROM did"]); goto test5,s,1; } 88 => { SET(LIMIT_PLAYAUDIO_CALLER=yes); SET(LIMIT_PLAYAUDIO_CALLEE=no); SET(LIMIT_TIMEOUT_FILE=timeup); SET(LIMIT_CONNECT_FILE=limit60); SET(LIMIT_WARNING_FILE=almostup); Dial(Zap/51,20,L(60000:30000:8000)); } 89 => { goto callbackmenu|100|1; } } context income1 { s => { Answer(); Dial(Zap/50,20,m); } 150 => Dial(Zap/50,20,m); } context callbackmenu { _X. => { Answer(); Wait(1); Set(TIMEOUT(digit)=5); Set(TIMEOUT(response)=30); DISA(no-password,callbackdialout); } } context callbackdialout { _X. => { Dial(Zap/51,20,w); } } macro dialoutpstn(something1, something2, something3, something4, something5) { Verbose(${something1}--- ${something2}--- ${something3}--- ${something4}--- ${something5}); } macro ndeep(level) { if( ${level} == 0) { Verbose(2|Got to Level 0); return; } &ndeep($[${level}-1]); return; } asterisk-1.6.1.0/README0000644000175000017500000003235211024256233013627 0ustar maniacmaniac=============================================================================== === The Asterisk(R) Open Source PBX === === by Mark Spencer === and the Asterisk.org developer community === === Copyright (C) 2001-2008 Digium, Inc. === and other copyright holders. =============================================================================== ------------------------------------------------------------------------------- --- SECURITY ------------------------------------------------------------------ It is imperative that you read and fully understand the contents of the security information document before you attempt to configure and run an Asterisk server. If you downloaded Asterisk as a tarball, see the security section in the PDF version of the documentation in doc/tex/asterisk.pdf. Alternatively, pull up the HTML version of the documentation in doc/tex/asterisk/index.html. The source for the security document is available in doc/tex/security.tex. ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- --- WHAT IS ASTERISK ? -------------------------------------------------------- Asterisk is an Open Source PBX and telephony toolkit. It is, in a sense, middleware between Internet and telephony channels on the bottom, and Internet and telephony applications at the top. However, Asterisk supports more telephony interfaces than just Internet telephony. Asterisk also has a vast amount of support for traditional PSTN telephony, as well. For more information on the project itself, please visit the Asterisk home page at: http://www.asterisk.org In addition you'll find lots of information compiled by the Asterisk community on this Wiki: http://www.voip-info.org/wiki-Asterisk There is a book on Asterisk published by O'Reilly under the Creative Commons License. It is available in book stores as well as in a downloadable version on the http://www.asteriskdocs.org web site. ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- --- SUPPORTED OPERATING SYSTEMS ----------------------------------------------- --- Linux The Asterisk Open Source PBX is developed and tested primarily on the GNU/Linux operating system, and is supported on every major GNU/Linux distribution. --- Others Asterisk has also been 'ported' and reportedly runs properly on other operating systems as well, including Sun Solaris, Apple's Mac OS X, Cygwin, and the BSD variants. ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- --- GETTING STARTED ----------------------------------------------------------- First, be sure you've got supported hardware (but note that you don't need ANY special hardware, not even a sound card) to install and run Asterisk. Supported telephony hardware includes: * All Analog and Digital Interface cards from Digium (www.digium.com) * QuickNet Internet PhoneJack and LineJack (http://www.quicknet.net) * any full duplex sound card supported by ALSA, OSS, or PortAudio * any ISDN card supported by mISDN on Linux (BRI) * The Xorcom AstriBank channel bank * VoiceTronix OpenLine products ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- --- UPGRADING FROM AN EARLIER VERSION ----------------------------------------- If you are updating from a previous version of Asterisk, make sure you read the UPGRADE.txt file in the source directory. There are some files and configuration options that you will have to change, even though we made every effort possible to maintain backwards compatibility. In order to discover new features to use, please check the configuration examples in the /configs directory of the source code distribution. For a list of new features in this version of Asterisk, see the CHANGES file. ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- --- NEW INSTALLATIONS --------------------------------------------------------- Ensure that your system contains a compatible compiler and development libraries. Asterisk requires either the GNU Compiler Collection (GCC) version 3.0 or higher, or a compiler that supports the C99 specification and some of the gcc language extensions. In addition, your system needs to have the C library headers available, and the headers and libraries for ncurses. There are many modules that have additional dependencies. To see what libraries are being looked for, see ./configure --help, or run "make menuselect" to view the dependencies for specific modules. On many distributions, these dependencies are installed by packages with names like 'glibc-devel', 'ncurses-devel', 'openssl-devel' and 'zlib-devel' or similar. So, let's proceed: 1) Read this README file. There are more documents than this one in the doc/ directory. You may also want to check the configuration files that contain examples and reference guides. They are all in the configs/ directory. 2) Run "./configure" Execute the configure script to guess values for system-dependent variables used during compilation. 3) Run "make menuselect" [optional] This is needed if you want to select the modules that will be compiled and to check dependencies for various optional modules. 4) Run "make" Assuming the build completes successfully: 5) Run "make install" If this is your first time working with Asterisk, you may wish to install the sample PBX, with demonstration extensions, etc. If so, run: 6) "make samples" Doing so will overwrite any existing configuration files you have installed. Finally, you can launch Asterisk in the foreground mode (not a daemon) with: # asterisk -vvvc You'll see a bunch of verbose messages fly by your screen as Asterisk initializes (that's the "very very verbose" mode). When it's ready, if you specified the "c" then you'll get a command line console, that looks like this: *CLI> You can type "help" at any time to get help with the system. For help with a specific command, type "help ". To start the PBX using your sound card, you can type "console dial" to dial the PBX. Then you can use "console answer", "console hangup", and "console dial" to simulate the actions of a telephone. Remember that if you don't have a full duplex sound card (and Asterisk will tell you somewhere in its verbose messages if you do/don't) then it won't work right (not yet). "man asterisk" at the Unix/Linux command prompt will give you detailed information on how to start and stop Asterisk, as well as all the command line options for starting Asterisk. Feel free to look over the configuration files in /etc/asterisk, where you will find a lot of information about what you can do with Asterisk. ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- --- ABOUT CONFIGURATION FILES ------------------------------------------------- All Asterisk configuration files share a common format. Comments are delimited by ';' (since '#' of course, being a DTMF digit, may occur in many places). A configuration file is divided into sections whose names appear in []'s. Each section typically contains two types of statements, those of the form 'variable = value', and those of the form 'object => parameters'. Internally the use of '=' and '=>' is exactly the same, so they're used only to help make the configuration file easier to understand, and do not affect how it is actually parsed. Entries of the form 'variable=value' set the value of some parameter in asterisk. For example, in dahdi.conf, one might specify: switchtype=national In order to indicate to Asterisk that the switch they are connecting to is of the type "national". In general, the parameter will apply to instantiations which occur below its specification. For example, if the configuration file read: switchtype = national channel => 1-4 channel => 10-12 switchtype = dms100 channel => 25-47 The "national" switchtype would be applied to channels one through four and channels 10 through 12, whereas the "dms100" switchtype would apply to channels 25 through 47. The "object => parameters" instantiates an object with the given parameters. For example, the line "channel => 25-47" creates objects for the channels 25 through 47 of the card, obtaining the settings from the variables specified above. ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- --- SPECIAL NOTE ON TIME ------------------------------------------------------ Those using SIP phones should be aware that Asterisk is sensitive to large jumps in time. Manually changing the system time using date(1) (or other similar commands) may cause SIP registrations and other internal processes to fail. If your system cannot keep accurate time by itself use NTP (http://www.ntp.org/) to keep the system clock synchronized to "real time". NTP is designed to keep the system clock synchronized by speeding up or slowing down the system clock until it is synchronized to "real time" rather than by jumping the time and causing discontinuities. Most Linux distributions include precompiled versions of NTP. Beware of some time synchronization methods that get the correct real time periodically and then manually set the system clock. Apparent time changes due to daylight savings time are just that, apparent. The use of daylight savings time in a Linux system is purely a user interface issue and does not affect the operation of the Linux kernel or Asterisk. The system clock on Linux kernels operates on UTC. UTC does not use daylight savings time. Also note that this issue is separate from the clocking of TDM channels, and is known to at least affect SIP registrations. ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- --- FILE DESCRIPTORS ---------------------------------------------------------- Depending on the size of your system and your configuration, Asterisk can consume a large number of file descriptors. In UNIX, file descriptors are used for more than just files on disk. File descriptors are also used for handling network communication (e.g. SIP, IAX2, or H.323 calls) and hardware access (e.g. analog and digital trunk hardware). Asterisk accesses many on-disk files for everything from configuration information to voicemail storage. Most systems limit the number of file descriptors that Asterisk can have open at one time. This can limit the number of simultaneous calls that your system can handle. For example, if the limit is set at 1024 (a common default value) Asterisk can handle approximately 150 SIP calls simultaneously. To change the number of file descriptors follow the instructions for your system below: ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- --- PAM-based Linux System ---------------------------------------------------- If your system uses PAM (Pluggable Authentication Modules) edit /etc/security/limits.conf. Add these lines to the bottom of the file: root soft nofile 4096 root hard nofile 8196 asterisk soft nofile 4096 asterisk hard nofile 8196 (adjust the numbers to taste). You may need to reboot the system for these changes to take effect. == Generic UNIX System == If there are no instructions specifically adapted to your system above you can try adding the command "ulimit -n 8192" to the script that starts Asterisk. ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- --- MORE INFORMATION ---------------------------------------------------------- See the doc directory for more documentation on various features. Again, please read all the configuration samples that include documentation on the configuration options. If this release of Asterisk was downloaded from a tarball, then some additional documentation should have been included. * doc/tex/asterisk.pdf --- PDF version of the documentation * doc/tex/asterisk/index.html --- HTML version of the documentation Finally, you may wish to visit the web site and join the mailing list if you're interested in getting more information. http://www.asterisk.org/support Welcome to the growing worldwide community of Asterisk users! ------------------------------------------------------------------------------- --- Mark Spencer, and the Asterisk.org development community ------------------------------------------------------------------------------- Asterisk is a trademark of Digium, Inc. asterisk-1.6.1.0/mkinstalldirs0000755000175000017500000000132410427665642015566 0ustar maniacmaniac#! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain # $Id: mkinstalldirs 25628 2006-05-08 16:02:42Z kpfleming $ errstatus=0 for file do set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` shift pathcomp= for d do pathcomp="$pathcomp$d" case "$pathcomp" in -* ) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr fi fi pathcomp="$pathcomp/" done done exit $errstatus # mkinstalldirs ends here asterisk-1.6.1.0/agi/0000755000175000017500000000000011175405521013505 5ustar maniacmaniacasterisk-1.6.1.0/agi/Makefile0000644000175000017500000000210211167302251015135 0ustar maniacmaniac# # Asterisk -- A telephony toolkit for Linux. # # Makefile for AGI-related stuff # # Copyright (C) 1999-2006, Digium # # Mark Spencer # # This program is free software, distributed under the terms of # the GNU General Public License # .PHONY: clean all uninstall AGIS=agi-test.agi eagi-test eagi-sphinx-test jukebox.agi ifeq ($(OSARCH),SunOS) LIBS+=-lsocket -lnsl endif ifeq ($(OSARCH),mingw32) AGIS:= endif include $(ASTTOPDIR)/Makefile.rules ASTCFLAGS+=-DSTANDALONE all: $(AGIS) strcompat.c: ../main/strcompat.c @cp $< $@ strcompat.o: ASTCFLAGS+=-DSTANDALONE eagi-test.o: ASTCFLAGS+=-DSTANDALONE eagi-test: eagi-test.o strcompat.o eagi-sphinx-test.o: ASTCFLAGS+=-DSTANDALONE eagi-sphinx-test: eagi-sphinx-test.o install: all mkdir -p $(DESTDIR)$(AGI_DIR) for x in $(AGIS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(AGI_DIR) ; done uninstall: for x in $(AGIS); do rm -f $(DESTDIR)$(AGI_DIR)/$$x ; done clean: rm -f *.so *.o look eagi-test eagi-sphinx-test rm -f .*.d *.s *.i rm -f strcompat.c ifneq ($(wildcard .*.d),) include .*.d endif asterisk-1.6.1.0/agi/fastagi-test0000644000175000017500000000426710374426007016036 0ustar maniacmaniac#!/usr/bin/perl use strict; use Socket; use Carp; use IO::Handle; my $port = 4573; $|=1; # Setup some variables my %AGI; my $tests = 0; my $fail = 0; my $pass = 0; sub checkresult { my ($res) = @_; my $retval; $tests++; chomp $res; if ($res =~ /^200/) { $res =~ /result=(-?\d+)/; if (!length($1)) { print STDERR "FAIL ($res)\n"; $fail++; } else { print STDERR "PASS ($1)\n"; $pass++; } } else { print STDERR "FAIL (unexpected result '$res')\n"; $fail++; } } socket(SERVER, PF_INET, SOCK_STREAM, 0); setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)); bind(SERVER, sockaddr_in($port, INADDR_ANY)) || die("can't bind\n"); listen(SERVER, SOMAXCONN); for(;;) { my $raddr = accept(CLIENT, SERVER); my ($s, $p) = sockaddr_in($raddr); CLIENT->autoflush(1); while() { chomp; last unless length($_); if (/^agi_(\w+)\:\s+(.*)$/) { $AGI{$1} = $2; } } print STDERR "AGI Environment Dump from $s:$p --\n"; foreach my $i (sort keys %AGI) { print STDERR " -- $i = $AGI{$i}\n"; } print STDERR "1. Testing 'sendfile'..."; print CLIENT "STREAM FILE beep \"\"\n"; my $result = ; &checkresult($result); print STDERR "2. Testing 'sendtext'..."; print CLIENT "SEND TEXT \"hello world\"\n"; my $result = ; &checkresult($result); print STDERR "3. Testing 'sendimage'..."; print CLIENT "SEND IMAGE asterisk-image\n"; my $result = ; &checkresult($result); print STDERR "4. Testing 'saynumber'..."; print CLIENT "SAY NUMBER 192837465 \"\"\n"; my $result = ; &checkresult($result); print STDERR "5. Testing 'waitdtmf'..."; print CLIENT "WAIT FOR DIGIT 1000\n"; my $result = ; &checkresult($result); print STDERR "6. Testing 'record'..."; print CLIENT "RECORD FILE testagi gsm 1234 3000\n"; my $result = ; &checkresult($result); print STDERR "6a. Testing 'record' playback..."; print CLIENT "STREAM FILE testagi \"\"\n"; my $result = ; &checkresult($result); close(CLIENT); print STDERR "================== Complete ======================\n"; print STDERR "$tests tests completed, $pass passed, $fail failed\n"; print STDERR "==================================================\n"; } asterisk-1.6.1.0/agi/numeralize0000644000175000017500000000172210374426007015607 0ustar maniacmaniac#!/usr/bin/perl # # Build a database linking filenames to their numerical representations # using a keypad for the DialAnMp3 application # $mp3dir="/usr/media/mpeg3"; dbmopen(%DIGITS, "/var/lib/asterisk/mp3list", 0644) || die("Unable to open mp3list");; sub process_dir { my ($dir) = @_; my $file; my $digits; my @entries; opendir(DIR, $dir); @entries = readdir(DIR); closedir(DIR); foreach $_ (@entries) { if (!/^\./) { $file = "$dir/$_"; if (-d "$file") { process_dir("$file"); } else { $digits = $_; $digits =~ s/[^ \w]+//g; $digits =~ s/\_/ /g; $digits =~ tr/[a-z]/[A-Z]/; $digits =~ tr/[A-C]/2/; $digits =~ tr/[D-F]/3/; $digits =~ tr/[G-I]/4/; $digits =~ tr/[J-L]/5/; $digits =~ tr/[M-O]/6/; $digits =~ tr/[P-S]/7/; $digits =~ tr/[T-V]/8/; $digits =~ tr/[W-Z]/9/; $digits =~ s/\s+/ /; print "File: $file, digits: $digits\n"; $DIGITS{$file} = $digits; } } } } process_dir($mp3dir); asterisk-1.6.1.0/agi/eagi-test.c0000644000175000017500000000722211103437035015532 0ustar maniacmaniac/* * Extended AGI test application * * This code is released into the public domain * with no warranty of any kind */ #include "asterisk.h" #define AUDIO_FILENO (STDERR_FILENO + 1) /*! \file * Extended AGI test application * * This code is released into the public domain * with no warranty of any kind * * \ingroup agi */ static int read_environment(void) { char buf[256]; char *val; /* Read environment */ for(;;) { if (!fgets(buf, sizeof(buf), stdin)) { return -1; } if (feof(stdin)) return -1; buf[strlen(buf) - 1] = '\0'; /* Check for end of environment */ if (!strlen(buf)) return 0; val = strchr(buf, ':'); if (!val) { fprintf(stderr, "Invalid environment: '%s'\n", buf); return -1; } *val = '\0'; val++; val++; /* Skip space */ fprintf(stderr, "Environment: '%s' is '%s'\n", buf, val); /* Load into normal environment */ setenv(buf, val, 1); } /* Never reached */ return 0; } static char *wait_result(void) { fd_set fds; int res; int bytes = 0; static char astresp[256]; char audiobuf[4096]; for (;;) { FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds); FD_SET(AUDIO_FILENO, &fds); /* Wait for *some* sort of I/O */ res = select(AUDIO_FILENO + 1, &fds, NULL, NULL, NULL); if (res < 0) { fprintf(stderr, "Error in select: %s\n", strerror(errno)); return NULL; } if (FD_ISSET(STDIN_FILENO, &fds)) { if (!fgets(astresp, sizeof(astresp), stdin)) { return NULL; } if (feof(stdin)) { fprintf(stderr, "Got hungup on apparently\n"); return NULL; } astresp[strlen(astresp) - 1] = '\0'; fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp); return astresp; } if (FD_ISSET(AUDIO_FILENO, &fds)) { res = read(AUDIO_FILENO, audiobuf, sizeof(audiobuf)); if (res > 0) { /* XXX Process the audio with sphinx here XXX */ #if 0 fprintf(stderr, "Got %d/%d bytes of audio\n", res, bytes); #endif bytes += res; /* Prentend we detected some audio after 3 seconds */ if (bytes > 16000 * 3) { return "Sample Message"; bytes = 0; } } } } } static char *run_command(char *command) { fprintf(stdout, "%s\n", command); return wait_result(); } static int run_script(void) { char *res; res = run_command("STREAM FILE demo-enterkeywords 0123456789*#"); if (!res) { fprintf(stderr, "Failed to execute command\n"); return -1; } fprintf(stderr, "1. Result is '%s'\n", res); res = run_command("STREAM FILE demo-nomatch 0123456789*#"); if (!res) { fprintf(stderr, "Failed to execute command\n"); return -1; } fprintf(stderr, "2. Result is '%s'\n", res); res = run_command("SAY NUMBER 23452345 0123456789*#"); if (!res) { fprintf(stderr, "Failed to execute command\n"); return -1; } fprintf(stderr, "3. Result is '%s'\n", res); res = run_command("GET DATA demo-enterkeywords"); if (!res) { fprintf(stderr, "Failed to execute command\n"); return -1; } fprintf(stderr, "4. Result is '%s'\n", res); res = run_command("STREAM FILE auth-thankyou \"\""); if (!res) { fprintf(stderr, "Failed to execute command\n"); return -1; } fprintf(stderr, "5. Result is '%s'\n", res); return 0; } int main(int argc, char *argv[]) { char *tmp; int ver = 0; int subver = 0; /* Setup stdin/stdout for line buffering */ setlinebuf(stdin); setlinebuf(stdout); if (read_environment()) { fprintf(stderr, "Failed to read environment: %s\n", strerror(errno)); exit(1); } tmp = getenv("agi_enhanced"); if (tmp) { if (sscanf(tmp, "%d.%d", &ver, &subver) != 2) ver = 0; } if (ver < 1) { fprintf(stderr, "No enhanced AGI services available. Use EAGI, not AGI\n"); exit(1); } if (run_script()) return -1; exit(0); } asterisk-1.6.1.0/agi/eagi-sphinx-test.c0000644000175000017500000001253211103437035017041 0ustar maniacmaniac/* * Extended AGI test application * * This code is released into public domain * without any warranty of any kind. * */ /*! \file * Extended AGI test application * * This code is released into public domain * without any warranty of any kind. * * \ingroup agi */ #include #include #include #include #include #include #include #include #include #include #include #include "asterisk.h" #include "asterisk/compat.h" #define AUDIO_FILENO (STDERR_FILENO + 1) #define SPHINX_HOST "192.168.1.108" #define SPHINX_PORT 3460 static int sphinx_sock = -1; static int connect_sphinx(void) { struct hostent *hp; struct sockaddr_in sin; int res; hp = gethostbyname(SPHINX_HOST); if (!hp) { fprintf(stderr, "Unable to resolve '%s'\n", SPHINX_HOST); return -1; } sphinx_sock = socket(PF_INET, SOCK_STREAM, 0); if (sphinx_sock < 0) { fprintf(stderr, "Unable to allocate socket: %s\n", strerror(errno)); return -1; } memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(SPHINX_PORT); memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); if (connect(sphinx_sock, (struct sockaddr *)&sin, sizeof(sin))) { fprintf(stderr, "Unable to connect on socket: %s\n", strerror(errno)); close(sphinx_sock); sphinx_sock = -1; return -1; } res = fcntl(sphinx_sock, F_GETFL); if ((res < 0) || (fcntl(sphinx_sock, F_SETFL, res | O_NONBLOCK) < 0)) { fprintf(stderr, "Unable to set flags on socket: %s\n", strerror(errno)); close(sphinx_sock); sphinx_sock = -1; return -1; } return 0; } static int read_environment(void) { char buf[256]; char *val; /* Read environment */ for(;;) { if (!fgets(buf, sizeof(buf), stdin)) { return -1; } if (feof(stdin)) return -1; buf[strlen(buf) - 1] = '\0'; /* Check for end of environment */ if (!strlen(buf)) return 0; val = strchr(buf, ':'); if (!val) { fprintf(stderr, "Invalid environment: '%s'\n", buf); return -1; } *val = '\0'; val++; val++; /* Skip space */ fprintf(stderr, "Environment: '%s' is '%s'\n", buf, val); /* Load into normal environment */ setenv(buf, val, 1); } /* Never reached */ return 0; } static char *wait_result(void) { fd_set fds; int res; int max; static char astresp[256]; static char sphinxresp[256]; char audiobuf[4096]; for (;;) { FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds); FD_SET(AUDIO_FILENO, &fds); max = AUDIO_FILENO; if (sphinx_sock > -1) { FD_SET(sphinx_sock, &fds); if (sphinx_sock > max) max = sphinx_sock; } /* Wait for *some* sort of I/O */ res = select(max + 1, &fds, NULL, NULL, NULL); if (res < 0) { fprintf(stderr, "Error in select: %s\n", strerror(errno)); return NULL; } if (FD_ISSET(STDIN_FILENO, &fds)) { if (!fgets(astresp, sizeof(astresp), stdin)) { return NULL; } if (feof(stdin)) { fprintf(stderr, "Got hungup on apparently\n"); return NULL; } astresp[strlen(astresp) - 1] = '\0'; fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp); return astresp; } if (FD_ISSET(AUDIO_FILENO, &fds)) { res = read(AUDIO_FILENO, audiobuf, sizeof(audiobuf)); if ((res > 0) && (sphinx_sock > -1)) { if (write(sphinx_sock, audiobuf, res) < 0) { fprintf(stderr, "write() failed: %s\n", strerror(errno)); } } } if ((sphinx_sock > -1) && FD_ISSET(sphinx_sock, &fds)) { res = read(sphinx_sock, sphinxresp, sizeof(sphinxresp)); if (res > 0) { fprintf(stderr, "Oooh, Sphinx found a token: '%s'\n", sphinxresp); return sphinxresp; } else if (res == 0) { fprintf(stderr, "Hrm, lost sphinx, guess we're on our own\n"); close(sphinx_sock); sphinx_sock = -1; } } } } static char *run_command(char *command) { fprintf(stdout, "%s\n", command); return wait_result(); } static int run_script(void) { char *res; res = run_command("STREAM FILE demo-enterkeywords 0123456789*#"); if (!res) { fprintf(stderr, "Failed to execute command\n"); return -1; } fprintf(stderr, "1. Result is '%s'\n", res); res = run_command("STREAM FILE demo-nomatch 0123456789*#"); if (!res) { fprintf(stderr, "Failed to execute command\n"); return -1; } fprintf(stderr, "2. Result is '%s'\n", res); res = run_command("SAY NUMBER 23452345 0123456789*#"); if (!res) { fprintf(stderr, "Failed to execute command\n"); return -1; } fprintf(stderr, "3. Result is '%s'\n", res); res = run_command("GET DATA demo-enterkeywords"); if (!res) { fprintf(stderr, "Failed to execute command\n"); return -1; } fprintf(stderr, "4. Result is '%s'\n", res); res = run_command("STREAM FILE auth-thankyou \"\""); if (!res) { fprintf(stderr, "Failed to execute command\n"); return -1; } fprintf(stderr, "5. Result is '%s'\n", res); return 0; } int main(int argc, char *argv[]) { char *tmp; int ver = 0; int subver = 0; /* Setup stdin/stdout for line buffering */ setlinebuf(stdin); setlinebuf(stdout); if (read_environment()) { fprintf(stderr, "Failed to read environment: %s\n", strerror(errno)); exit(1); } connect_sphinx(); tmp = getenv("agi_enhanced"); if (tmp) { if (sscanf(tmp, "%d.%d", &ver, &subver) != 2) ver = 0; } if (ver < 1) { fprintf(stderr, "No enhanced AGI services available. Use EAGI, not AGI\n"); exit(1); } if (run_script()) return -1; exit(0); } asterisk-1.6.1.0/agi/jukebox.agi0000755000175000017500000003430210403144641015637 0ustar maniacmaniac#!/usr/bin/perl # # Jukebox 0.2 # # A music manager for Asterisk. # # Copyright (C) 2005-2006, Justin Tunney # # Justin Tunney # # This program is free software, distributed under the terms of the # GNU General Public License v2. # # Keep it open source pigs # # -------------------------------------------------------------------- # # Uses festival to list off all your MP3 music files over a channel in # a hierarchical fashion. Put this file in your agi-bin folder which # is located at: /var/lib/asterisk/agi-bin Be sure to chmod +x it! # # Invocation Example: # exten => 68742,1,Answer() # exten => 68742,2,agi,jukebox.agi|/home/justin/Music # exten => 68742,3,Hangup() # # exten => 68742,1,Answer() # exten => 68742,2,agi,jukebox.agi|/home/justin/Music|pm # exten => 68742,3,Hangup() # # Options: # p - Precache text2wave outputs for every possible filename. # It is much better to set this option because if a caller # presses a key during a cache operation, it will be ignored. # m - Go back to menu after playing song # g - Do not play the greeting message # # Usage Instructions: # - Press '*' to go up a directory. If you are in the root music # folder you will be exitted from the script. # - If you have a really long list of files, you can filter the list # at any time by pressing '#' and spelling out a few letters you # expect the files to start with. For example, if you wanted to # know what extension 'Requiem For A Dream' was, you'd type: # '#737'. Note, phone keypads don't include Q and Z. Q is 7 and # Z is 9. # # Notes: # - This AGI script uses the MP3Player command which uses the # mpg123 Program. Grab yourself a copy of this program by # going to http://www.mpg123.de/cgi-bin/sitexplorer.cgi?/mpg123/ # Be sure to download mpg123-0.59r.tar.gz because it is known to # work with Asterisk and hopefully isn't the release with that # awful security problem. If you're using Fedora Core 3 with # Alsa like me, make linux-alsa isn't going to work. Do make # linux-devel and you're peachy keen. # # - You won't get nifty STDERR debug messages if you're using a # remote asterisk shell. # # - For some reason, caching certain files will generate the # error: 'using default diphone ax-ax for y-pau'. Example: # # echo "Depeche Mode - CUW - 05 - The Meaning of Love" | text2wave -o /var/jukeboxcache/jukeboxcache/Depeche_Mode/Depeche_Mode_-_CUW_-_05_-_The_Meaning_of_Love.mp3.ul -otype ulaw - # The temporary work around is to just touch these files. # # - The background app doesn't like to get more than 2031 chars # of input. # use strict; $|=1; # Setup some variables my %AGI; my $tests = 0; my $fail = 0; my $pass = 0; my @masterCacheList = (); my $maxNumber = 10; while () { chomp; last unless length($_); if (/^agi_(\w+)\:\s+(.*)$/) { $AGI{$1} = $2; } } # setup options my $SHOWGREET = 1; my $PRECACHE = 0; my $MENUAFTERSONG = 0; $PRECACHE = 1 if $ARGV[1] =~ /p/; $MENUAFTERSONG = 1 if $ARGV[1] =~ /m/; $SHOWGREET = 0 if $ARGV[1] =~ /g/; # setup folders my $MUSIC = $ARGV[0]; $MUSIC = &rmts($MUSIC); my $FESTIVALCACHE = "/var/jukeboxcache"; if (! -e $FESTIVALCACHE) { `mkdir -p -m0776 $FESTIVALCACHE`; } # make sure we have some essential files if (! -e "$FESTIVALCACHE/jukebox_greet.ul") { `echo "Welcome to the Asterisk Jukebox" | text2wave -o $FESTIVALCACHE/jukebox_greet.ul -otype ulaw -`; } if (! -e "$FESTIVALCACHE/jukebox_press.ul") { `echo "Press" | text2wave -o $FESTIVALCACHE/jukebox_press.ul -otype ulaw -`; } if (! -e "$FESTIVALCACHE/jukebox_for.ul") { `echo "For" | text2wave -o $FESTIVALCACHE/jukebox_for.ul -otype ulaw -`; } if (! -e "$FESTIVALCACHE/jukebox_toplay.ul") { `echo "To play" | text2wave -o $FESTIVALCACHE/jukebox_toplay.ul -otype ulaw -`; } if (! -e "$FESTIVALCACHE/jukebox_nonefound.ul") { `echo "There were no music files found in this folder" | text2wave -o $FESTIVALCACHE/jukebox_nonefound.ul -otype ulaw -`; } if (! -e "$FESTIVALCACHE/jukebox_percent.ul") { `echo "Percent" | text2wave -o $FESTIVALCACHE/jukebox_percent.ul -otype ulaw -`; } if (! -e "$FESTIVALCACHE/jukebox_generate.ul") { `echo "Please wait while Astrisk Jukebox cashes the files of your music collection" | text2wave -o $FESTIVALCACHE/jukebox_generate.ul -otype ulaw -`; } if (! -e "$FESTIVALCACHE/jukebox_invalid.ul") { `echo "You have entered an invalid selection" | text2wave -o $FESTIVALCACHE/jukebox_invalid.ul -otype ulaw -`; } if (! -e "$FESTIVALCACHE/jukebox_thankyou.ul") { `echo "Thank you for using Astrisk Jukebox, Goodbye" | text2wave -o $FESTIVALCACHE/jukebox_thankyou.ul -otype ulaw -`; } # greet the user if ($SHOWGREET) { print "EXEC Playback \"$FESTIVALCACHE/jukebox_greet\"\n"; my $result = ; &check_result($result); } # go through the directories music_dir_cache() if $PRECACHE; music_dir_menu('/'); exit 0; ########################################################################## sub music_dir_menu { my $dir = shift; # generate a list of mp3's and directories and assign each one it's # own selection number. Then make sure that we've got a sound clip # for the file name if (!opendir(THEDIR, rmts($MUSIC.$dir))) { print STDERR "Failed to open music directory: $dir\n"; exit 1; } my @files = sort readdir THEDIR; my $cnt = 1; my @masterBgList = (); foreach my $file (@files) { chomp($file); if ($file ne '.' && $file ne '..' && $file ne 'festivalcache') { # ignore special files my $real_version = &rmts($MUSIC.$dir).'/'.$file; my $cache_version = &rmts($FESTIVALCACHE.$dir).'/'.$file.'.ul'; my $cache_version2 = &rmts($FESTIVALCACHE.$dir).'/'.$file; my $cache_version_esc = &clean_file($cache_version); my $cache_version2_esc = &clean_file($cache_version2); if (-d $real_version) { # 0:id 1:type 2:text2wav-file 3:for-filtering 4:the-directory 5:text2wav echo push(@masterBgList, [$cnt++, 1, $cache_version2_esc, &remove_special_chars($file), $file, "for the $file folder"]); } elsif ($real_version =~ /\.mp3$/) { # 0:id 1:type 2:text2wav-file 3:for-filtering 4:the-mp3 push(@masterBgList, [$cnt++, 2, $cache_version2_esc, &remove_special_chars($file), $real_version, "to play $file"]); } } } close(THEDIR); my @filterList = @masterBgList; if (@filterList == 0) { print "EXEC Playback \"$FESTIVALCACHE/jukebox_nonefound\"\n"; my $result = ; &check_result($result); return 0; } for (;;) { MYCONTINUE: # play bg selections and figure out their selection my $digit = ''; my $digitstr = ''; for (my $n=0; $n<@filterList; $n++) { &cache_speech(&remove_file_extension($filterList[$n][5]), "$filterList[$n][2].ul") if ! -e "$filterList[$n][2].ul"; &cache_speech("Press $filterList[$n][0]", "$FESTIVALCACHE/jukebox_$filterList[$n][0].ul") if ! -e "$FESTIVALCACHE/jukebox_$filterList[$n][0].ul"; print "EXEC Background \"$filterList[$n][2]&$FESTIVALCACHE/jukebox_$filterList[$n][0]\"\n"; my $result = ; $digit = &check_result($result); if ($digit > 0) { $digitstr .= chr($digit); last; } } for (;;) { print "WAIT FOR DIGIT 3000\n"; my $result = ; $digit = &check_result($result); last if $digit <= 0; $digitstr .= chr($digit); } # see if it's a valid selection print STDERR "Digits Entered: '$digitstr'\n"; exit 0 if $digitstr eq ''; my $found = 0; goto EXITSUB if $digitstr =~ /\*/; # filter the list if ($digitstr =~ /^\#\d+/) { my $regexp = ''; for (my $n=1; $n; &check_result($result); `rm $link`; if (!$MENUAFTERSONG) { print "EXEC Playback \"$FESTIVALCACHE/jukebox_thankyou\"\n"; my $result = ; &check_result($result); exit 0; } else { goto MYCONTINUE; } } } } print "EXEC Playback \"$FESTIVALCACHE/jukebox_invalid\"\n"; my $result = ; &check_result($result); } EXITSUB: } sub cache_speech { my $speech = shift; my $file = shift; my $theDir = extract_file_dir($file); `mkdir -p -m0776 $theDir`; print STDERR "echo \"$speech\" | text2wave -o $file -otype ulaw -\n"; my $cmdr = `echo "$speech" | text2wave -o $file -otype ulaw -`; chomp($cmdr); if ($cmdr =~ /using default diphone/) { # temporary bug work around.... `touch $file`; } elsif ($cmdr ne '') { print STDERR "Command Failed\n"; exit 1; } } sub music_dir_cache { # generate list of text2speech files to generate if (!music_dir_cache_genlist('/')) { print STDERR "Horrible Dreadful Error: No Music Found in $MUSIC!"; exit 1; } # add to list how many 'number' files we have to generate. We can't # use the SayNumber app in Asterisk because we want to chain all # talking in one Background command. We also want a consistent # voice... for (my $n=1; $n<=$maxNumber; $n++) { push(@masterCacheList, [3, "Press $n", "$FESTIVALCACHE/jukebox_$n.ul"]) if ! -e "$FESTIVALCACHE/jukebox_$n.ul"; } # now generate all these darn text2speech files if (@masterCacheList > 5) { print "EXEC Playback \"$FESTIVALCACHE/jukebox_generate\"\n"; my $result = ; &check_result($result); } my $theTime = time(); for (my $n=0; $n < @masterCacheList; $n++) { my $cmdr = ''; if ($masterCacheList[$n][0] == 1) { # directory &cache_speech("for folder $masterCacheList[$n][1]", $masterCacheList[$n][2]); } elsif ($masterCacheList[$n][0] == 2) { # file &cache_speech("to play $masterCacheList[$n][1]", $masterCacheList[$n][2]); } elsif ($masterCacheList[$n][0] == 3) { # number &cache_speech($masterCacheList[$n][1], $masterCacheList[$n][2]); } if (time() >= $theTime + 30) { my $percent = int($n / @masterCacheList * 100); print "SAY NUMBER $percent \"\"\n"; my $result = ; &check_result($result); print "EXEC Playback \"$FESTIVALCACHE/jukebox_percent\"\n"; my $result = ; &check_result($result); $theTime = time(); } } } # this function will fill the @masterCacheList of all the files that # need to have text2speeced ulaw files of their names generated sub music_dir_cache_genlist { my $dir = shift; if (!opendir(THEDIR, rmts($MUSIC.$dir))) { print STDERR "Failed to open music directory: $dir\n"; exit 1; } my @files = sort readdir THEDIR; my $foundFiles = 0; my $tmpMaxNum = 0; foreach my $file (@files) { chomp; if ($file ne '.' && $file ne '..' && $file ne 'festivalcache') { # ignore special files my $real_version = &rmts($MUSIC.$dir).'/'.$file; my $cache_version = &rmts($FESTIVALCACHE.$dir).'/'.$file.'.ul'; my $cache_version2 = &rmts($FESTIVALCACHE.$dir).'/'.$file; my $cache_version_esc = &clean_file($cache_version); my $cache_version2_esc = &clean_file($cache_version2); if (-d $real_version) { if (music_dir_cache_genlist(rmts($dir).'/'.$file)) { $tmpMaxNum++; $maxNumber = $tmpMaxNum if $tmpMaxNum > $maxNumber; push(@masterCacheList, [1, $file, $cache_version_esc]) if ! -e $cache_version_esc; $foundFiles = 1; } } elsif ($real_version =~ /\.mp3$/) { $tmpMaxNum++; $maxNumber = $tmpMaxNum if $tmpMaxNum > $maxNumber; push(@masterCacheList, [2, &remove_file_extension($file), $cache_version_esc]) if ! -e $cache_version_esc; $foundFiles = 1; } } } close(THEDIR); return $foundFiles; } sub rmts { # remove trailing slash my $hog = shift; $hog =~ s/\/$//; return $hog; } sub extract_file_name { my $hog = shift; $hog =~ /\/?([^\/]+)$/; return $1; } sub extract_file_dir { my $hog = shift; return $hog if ! ($hog =~ /\//); $hog =~ /(.*)\/[^\/]*$/; return $1; } sub remove_file_extension { my $hog = shift; return $hog if ! ($hog =~ /\./); $hog =~ /(.*)\.[^.]*$/; return $1; } sub clean_file { my $hog = shift; $hog =~ s/\\/_/g; $hog =~ s/ /_/g; $hog =~ s/\t/_/g; $hog =~ s/\'/_/g; $hog =~ s/\"/_/g; $hog =~ s/\(/_/g; $hog =~ s/\)/_/g; $hog =~ s/&/_/g; $hog =~ s/\[/_/g; $hog =~ s/\]/_/g; $hog =~ s/\$/_/g; $hog =~ s/\|/_/g; $hog =~ s/\^/_/g; return $hog; } sub remove_special_chars { my $hog = shift; $hog =~ s/\\//g; $hog =~ s/ //g; $hog =~ s/\t//g; $hog =~ s/\'//g; $hog =~ s/\"//g; $hog =~ s/\(//g; $hog =~ s/\)//g; $hog =~ s/&//g; $hog =~ s/\[//g; $hog =~ s/\]//g; $hog =~ s/\$//g; $hog =~ s/\|//g; $hog =~ s/\^//g; return $hog; } sub escape_file { my $hog = shift; $hog =~ s/\\/\\\\/g; $hog =~ s/ /\\ /g; $hog =~ s/\t/\\\t/g; $hog =~ s/\'/\\\'/g; $hog =~ s/\"/\\\"/g; $hog =~ s/\(/\\\(/g; $hog =~ s/\)/\\\)/g; $hog =~ s/&/\\&/g; $hog =~ s/\[/\\\[/g; $hog =~ s/\]/\\\]/g; $hog =~ s/\$/\\\$/g; $hog =~ s/\|/\\\|/g; $hog =~ s/\^/\\\^/g; return $hog; } sub check_result { my ($res) = @_; my $retval; $tests++; chomp $res; if ($res =~ /^200/) { $res =~ /result=(-?\d+)/; if (!length($1)) { print STDERR "FAIL ($res)\n"; $fail++; exit 1; } else { print STDERR "PASS ($1)\n"; return $1; } } else { print STDERR "FAIL (unexpected result '$res')\n"; exit 1; } } asterisk-1.6.1.0/agi/DialAnMp3.agi0000644000175000017500000000334010374426007015701 0ustar maniacmaniac#!/usr/bin/perl # # Simple AGI application to play mp3's selected by a user both using # xmms and over the phone itself. # $|=1; while() { chomp; last unless length($_); if (/^agi_(\w+)\:\s+(.*)$/) { $AGI{$1} = $2; } } print STDERR "AGI Environment Dump:\n"; foreach $i (sort keys %AGI) { print STDERR " -- $i = $AGI{$i}\n"; } dbmopen(%DIGITS, "/var/lib/asterisk/mp3list", 0644) || die("Unable to open mp3list");; sub checkresult { my ($res) = @_; my $retval; $tests++; chomp $res; if ($res =~ /^200/) { $res =~ /result=(-?[\w\*\#]+)/; return $1; } else { return -1; } } #print STDERR "1. Playing beep...\n"; #print "STREAM FILE beep \"\"\n"; #$result = ; #checkresult($result); print STDERR "2. Getting song name...\n"; print "GET DATA demo-enterkeywords\n"; $result = ; $digitstr = checkresult($result); if ($digitstr < 0) { exit(1); } $digitstr =~ s/\*/ /g; print STDERR "Resulting songname is $digitstr\n"; @searchwords = split (/\s+/, $digitstr); print STDERR "Searchwords: " . join(':', @searchwords) . "\n"; foreach $key (sort keys %DIGITS) { @words = split(/\s+/, $DIGITS{$key}); $match = 1; foreach $search (@searchwords) { $match = 0 unless grep(/$search/, @words); } if ($match > 0) { print STDERR "File $key matches\n"; # Play a beep print "STREAM FILE beep \"\"\n"; system("xmms", $key); $result = ; if (&checkresult($result) < 0) { exit 0; } print "EXEC MP3Player \"$key\"\n"; # print "WAIT FOR DIGIT 60000\n"; $result = ; if (&checkresult($result) < 0) { exit 0; } print STDERR "Got here...\n"; } } print STDERR "4. Testing 'saynumber' of $digitstr...\n"; print "STREAM FILE demo-nomatch\"\"\n"; $result = ; checkresult($result); asterisk-1.6.1.0/agi/agi-test.agi0000644000175000017500000000331610374426007015711 0ustar maniacmaniac#!/usr/bin/perl use strict; $|=1; # Setup some variables my %AGI; my $tests = 0; my $fail = 0; my $pass = 0; while() { chomp; last unless length($_); if (/^agi_(\w+)\:\s+(.*)$/) { $AGI{$1} = $2; } } print STDERR "AGI Environment Dump:\n"; foreach my $i (sort keys %AGI) { print STDERR " -- $i = $AGI{$i}\n"; } sub checkresult { my ($res) = @_; my $retval; $tests++; chomp $res; if ($res =~ /^200/) { $res =~ /result=(-?\d+)/; if (!length($1)) { print STDERR "FAIL ($res)\n"; $fail++; } else { print STDERR "PASS ($1)\n"; $pass++; } } else { print STDERR "FAIL (unexpected result '$res')\n"; $fail++; } } print STDERR "1. Testing 'sendfile'..."; print "STREAM FILE beep \"\"\n"; my $result = ; &checkresult($result); print STDERR "2. Testing 'sendtext'..."; print "SEND TEXT \"hello world\"\n"; my $result = ; &checkresult($result); print STDERR "3. Testing 'sendimage'..."; print "SEND IMAGE asterisk-image\n"; my $result = ; &checkresult($result); print STDERR "4. Testing 'saynumber'..."; print "SAY NUMBER 192837465 \"\"\n"; my $result = ; &checkresult($result); print STDERR "5. Testing 'waitdtmf'..."; print "WAIT FOR DIGIT 1000\n"; my $result = ; &checkresult($result); print STDERR "6. Testing 'record'..."; print "RECORD FILE testagi gsm 1234 3000\n"; my $result = ; &checkresult($result); print STDERR "6a. Testing 'record' playback..."; print "STREAM FILE testagi \"\"\n"; my $result = ; &checkresult($result); print STDERR "================== Complete ======================\n"; print STDERR "$tests tests completed, $pass passed, $fail failed\n"; print STDERR "==================================================\n"; asterisk-1.6.1.0/res/0000755000175000017500000000000011205221755013535 5ustar maniacmaniacasterisk-1.6.1.0/res/res_phoneprov.c0000644000175000017500000010716711131731735016610 0ustar maniacmaniac/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 1999 - 2008, Digium, Inc. * * Mark Spencer * Matthew Brooks * Terry Wilson * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. */ /*! \file * * \brief Phone provisioning application for the asterisk internal http server * * \author Matthew Brooks * \author Terry Wilson */ /*** MODULEINFO func_strings ***/ #include "asterisk.h" #include #include #include #ifdef SOLARIS #include #endif ASTERISK_FILE_VERSION(__FILE__, "$Revision: 168157 $") #include "asterisk/channel.h" #include "asterisk/file.h" #include "asterisk/paths.h" #include "asterisk/pbx.h" #include "asterisk/cli.h" #include "asterisk/module.h" #include "asterisk/http.h" #include "asterisk/utils.h" #include "asterisk/app.h" #include "asterisk/strings.h" #include "asterisk/stringfields.h" #include "asterisk/options.h" #include "asterisk/config.h" #include "asterisk/acl.h" #include "asterisk/astobj2.h" #include "asterisk/ast_version.h" #ifdef LOW_MEMORY #define MAX_PROFILE_BUCKETS 1 #define MAX_ROUTE_BUCKETS 1 #define MAX_USER_BUCKETS 1 #else #define MAX_PROFILE_BUCKETS 17 #define MAX_ROUTE_BUCKETS 563 #define MAX_USER_BUCKETS 563 #endif /* LOW_MEMORY */ #define VAR_BUF_SIZE 4096 /*! \brief for use in lookup_iface */ static struct in_addr __ourip = { .s_addr = 0x00000000, }; /* \note This enum and the pp_variable_list must be in the same order or * bad things happen! */ enum pp_variables { PP_MACADDRESS, PP_USERNAME, PP_FULLNAME, PP_SECRET, PP_LABEL, PP_CALLERID, PP_TIMEZONE, PP_LINENUMBER, PP_VAR_LIST_LENGTH, /* This entry must always be the last in the list */ }; /*! \brief Lookup table to translate between users.conf property names and * variables for use in phoneprov templates */ static const struct pp_variable_lookup { enum pp_variables id; const char * const user_var; const char * const template_var; } pp_variable_list[] = { { PP_MACADDRESS, "macaddress", "MAC" }, { PP_USERNAME, "username", "USERNAME" }, { PP_FULLNAME, "fullname", "DISPLAY_NAME" }, { PP_SECRET, "secret", "SECRET" }, { PP_LABEL, "label", "LABEL" }, { PP_CALLERID, "cid_number", "CALLERID" }, { PP_TIMEZONE, "timezone", "TIMEZONE" }, { PP_LINENUMBER, "linenumber", "LINE" }, }; /*! \brief structure to hold file data */ struct phoneprov_file { AST_DECLARE_STRING_FIELDS( AST_STRING_FIELD(format); /*!< After variable substitution, becomes route->uri */ AST_STRING_FIELD(template); /*!< Template/physical file location */ AST_STRING_FIELD(mime_type);/*!< Mime-type of the file */ ); AST_LIST_ENTRY(phoneprov_file) entry; }; /*! \brief structure to hold phone profiles read from phoneprov.conf */ struct phone_profile { AST_DECLARE_STRING_FIELDS( AST_STRING_FIELD(name); /*!< Name of phone profile */ AST_STRING_FIELD(default_mime_type); /*!< Default mime type if it isn't provided */ AST_STRING_FIELD(staticdir); /*!< Subdirectory that static files are stored in */ ); struct varshead *headp; /*!< List of variables set with 'setvar' in phoneprov.conf */ AST_LIST_HEAD_NOLOCK(, phoneprov_file) static_files; /*!< List of static files */ AST_LIST_HEAD_NOLOCK(, phoneprov_file) dynamic_files; /*!< List of dynamic files */ }; struct extension { AST_DECLARE_STRING_FIELDS( AST_STRING_FIELD(name); ); int index; struct varshead *headp; /*!< List of variables to substitute into templates */ AST_LIST_ENTRY(extension) entry; }; /*! \brief structure to hold users read from users.conf */ struct user { AST_DECLARE_STRING_FIELDS( AST_STRING_FIELD(macaddress); /*!< Mac address of user's phone */ ); struct phone_profile *profile; /*!< Profile the phone belongs to */ AST_LIST_HEAD_NOLOCK(, extension) extensions; }; /*! \brief structure to hold http routes (valid URIs, and the files they link to) */ struct http_route { AST_DECLARE_STRING_FIELDS( AST_STRING_FIELD(uri); /*!< The URI requested */ ); struct phoneprov_file *file; /*!< The file that links to the URI */ struct user *user; /*!< The user that has variables to substitute into the file * NULL in the case of a static route */ }; static struct ao2_container *profiles; static struct ao2_container *http_routes; static struct ao2_container *users; /*! \brief Extensions whose mime types we think we know */ static struct { char *ext; char *mtype; } mimetypes[] = { { "png", "image/png" }, { "xml", "text/xml" }, { "jpg", "image/jpeg" }, { "js", "application/x-javascript" }, { "wav", "audio/x-wav" }, { "mp3", "audio/mpeg" }, }; static char global_server[80] = ""; /*!< Server to substitute into templates */ static char global_serverport[6] = ""; /*!< Server port to substitute into templates */ static char global_default_profile[80] = ""; /*!< Default profile to use if one isn't specified */ /*! \brief List of global variables currently available: VOICEMAIL_EXTEN, EXTENSION_LENGTH */ static struct varshead global_variables; static ast_mutex_t globals_lock; /*! \brief Return mime type based on extension */ static char *ftype2mtype(const char *ftype) { int x; if (ast_strlen_zero(ftype)) return NULL; for (x = 0;x < ARRAY_LEN(mimetypes);x++) { if (!strcasecmp(ftype, mimetypes[x].ext)) return mimetypes[x].mtype; } return NULL; } /* iface is the interface (e.g. eth0); address is the return value */ static int lookup_iface(const char *iface, struct in_addr *address) { int mysock, res = 0; struct ifreq ifr; struct sockaddr_in *sin; memset(&ifr, 0, sizeof(ifr)); ast_copy_string(ifr.ifr_name, iface, sizeof(ifr.ifr_name)); mysock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); if (mysock < 0) { ast_log(LOG_ERROR, "Failed to create socket: %s\n", strerror(errno)); return -1; } res = ioctl(mysock, SIOCGIFADDR, &ifr); close(mysock); if (res < 0) { ast_log(LOG_WARNING, "Unable to get IP of %s: %s\n", iface, strerror(errno)); memcpy(address, &__ourip, sizeof(__ourip)); return -1; } else { sin = (struct sockaddr_in *)&ifr.ifr_addr; memcpy(address, &sin->sin_addr, sizeof(*address)); return 0; } } static struct phone_profile *unref_profile(struct phone_profile *prof) { ao2_ref(prof, -1); return NULL; } /*! \brief Return a phone profile looked up by name */ static struct phone_profile *find_profile(const char *name) { struct phone_profile tmp = { .name = name, }; return ao2_find(profiles, &tmp, OBJ_POINTER); } static int profile_hash_fn(const void *obj, const int flags) { const struct phone_profile *profile = obj; return ast_str_hash(profile->name); } static int profile_cmp_fn(void *obj, void *arg, int flags) { const struct phone_profile *profile1 = obj, *profile2 = arg; return !strcasecmp(profile1->name, profile2->name) ? CMP_MATCH | CMP_STOP : 0; } static void delete_file(struct phoneprov_file *file) { ast_string_field_free_memory(file); free(file); } static void profile_destructor(void *obj) { struct phone_profile *profile = obj; struct phoneprov_file *file; struct ast_var_t *var; while ((file = AST_LIST_REMOVE_HEAD(&profile->static_files, entry))) delete_file(file); while ((file = AST_LIST_REMOVE_HEAD(&profile->dynamic_files, entry))) delete_file(file); while ((var = AST_LIST_REMOVE_HEAD(profile->headp, entries))) ast_var_delete(var); ast_free(profile->headp); ast_string_field_free_memory(profile); } static struct http_route *unref_route(struct http_route *route) { ao2_ref(route, -1); return NULL; } static int routes_hash_fn(const void *obj, const int flags) { const struct http_route *route = obj; return ast_str_hash(route->uri); } static int routes_cmp_fn(void *obj, void *arg, int flags) { const struct http_route *route1 = obj, *route2 = arg; return !strcmp(route1->uri, route2->uri) ? CMP_MATCH | CMP_STOP : 0; } static void route_destructor(void *obj) { struct http_route *route = obj; ast_string_field_free_memory(route); } /*! \brief Read a TEXT file into a string and return the length */ static int load_file(const char *filename, char **ret) { int len = 0; FILE *f; if (!(f = fopen(filename, "r"))) { *ret = NULL; return -1; } fseek(f, 0, SEEK_END); len = ftell(f); fseek(f, 0, SEEK_SET); if (!(*ret = ast_malloc(len + 1))) return -2; if (len != fread(*ret, sizeof(char), len, f)) { free(*ret); *ret = NULL; return -3; } fclose(f); (*ret)[len] = '\0'; return len; } /*! \brief Set all timezone-related variables based on a zone (i.e. America/New_York) \param headp pointer to list of user variables \param zone A time zone. NULL sets variables based on timezone of the machine */ static void set_timezone_variables(struct varshead *headp, const char *zone) { time_t utc_time; int dstenable; time_t dststart; time_t dstend; struct ast_tm tm_info; int tzoffset; char buffer[21]; struct ast_var_t *var; struct timeval when; time(&utc_time); ast_get_dst_info(&utc_time, &dstenable, &dststart, &dstend, &tzoffset, zone); snprintf(buffer, sizeof(buffer), "%d", tzoffset); var = ast_var_assign("TZOFFSET", buffer); if (var) AST_LIST_INSERT_TAIL(headp, var, entries); if (!dstenable) return; if ((var = ast_var_assign("DST_ENABLE", "1"))) AST_LIST_INSERT_TAIL(headp, var, entries); when.tv_sec = dststart; ast_localtime(&when, &tm_info, zone); snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mon+1); if ((var = ast_var_assign("DST_START_MONTH", buffer))) AST_LIST_INSERT_TAIL(headp, var, entries); snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mday); if ((var = ast_var_assign("DST_START_MDAY", buffer))) AST_LIST_INSERT_TAIL(headp, var, entries); snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_hour); if ((var = ast_var_assign("DST_START_HOUR", buffer))) AST_LIST_INSERT_TAIL(headp, var, entries); when.tv_sec = dstend; ast_localtime(&when, &tm_info, zone); snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mon + 1); if ((var = ast_var_assign("DST_END_MONTH", buffer))) AST_LIST_INSERT_TAIL(headp, var, entries); snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mday); if ((var = ast_var_assign("DST_END_MDAY", buffer))) AST_LIST_INSERT_TAIL(headp, var, entries); snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_hour); if ((var = ast_var_assign("DST_END_HOUR", buffer))) AST_LIST_INSERT_TAIL(headp, var, entries); } /*! \brief Callback that is executed everytime an http request is received by this module */ static struct ast_str *phoneprov_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *vars, struct ast_variable *headers, int *status, char **title, int *contentlength) { struct http_route *route; struct http_route search_route = { .uri = uri, }; struct ast_str *result = ast_str_create(512); char path[PATH_MAX]; char *file = NULL; int len; int fd; char buf[256]; struct timeval now = ast_tvnow(); struct ast_tm tm; if (!(route = ao2_find(http_routes, &search_route, OBJ_POINTER))) { goto out404; } snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, route->file->template); if (!route->user) { /* Static file */ fd = open(path, O_RDONLY); if (fd < 0) { goto out500; } len = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); if (len < 0) { ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len); close(fd); goto out500; } ast_strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %Z", ast_localtime(&now, &tm, "GMT")); fprintf(ser->f, "HTTP/1.1 200 OK\r\n" "Server: Asterisk/%s\r\n" "Date: %s\r\n" "Connection: close\r\n" "Cache-Control: no-cache, no-store\r\n" "Content-Length: %d\r\n" "Content-Type: %s\r\n\r\n", ast_get_version(), buf, len, route->file->mime_type); while ((len = read(fd, buf, sizeof(buf))) > 0) { if (fwrite(buf, 1, len, ser->f) != len) { if (errno != EPIPE) { ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno)); } else { ast_debug(3, "Requester closed the connection while downloading '%s'\n", path); } break; } } close(fd); route = unref_route(route); return NULL; } else { /* Dynamic file */ int bufsize; char *tmp; len = load_file(path, &file); if (len < 0) { ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len); if (file) { ast_free(file); } goto out500; } if (!file) { goto out500; } /* XXX This is a hack -- maybe sum length of all variables in route->user->headp and add that? */ bufsize = len + VAR_BUF_SIZE; /* malloc() instead of alloca() here, just in case the file is bigger than * we have enough stack space for. */ if (!(tmp = ast_calloc(1, bufsize))) { if (file) { ast_free(file); } goto out500; } /* Unless we are overridden by serveriface or serveraddr, we set the SERVER variable to * the IP address we are listening on that the phone contacted for this config file */ if (ast_strlen_zero(global_server)) { struct sockaddr name; socklen_t namelen = sizeof(name); int res; if ((res = getsockname(ser->fd, &name, &namelen))) { ast_log(LOG_WARNING, "Could not get server IP, breakage likely.\n"); } else { struct ast_var_t *var; struct extension *exten_iter; if ((var = ast_var_assign("SERVER", ast_inet_ntoa(((struct sockaddr_in *)&name)->sin_addr)))) { AST_LIST_TRAVERSE(&route->user->extensions, exten_iter, entry) { AST_LIST_INSERT_TAIL(exten_iter->headp, var, entries); } } } } pbx_substitute_variables_varshead(AST_LIST_FIRST(&route->user->extensions)->headp, file, tmp, bufsize); if (file) { ast_free(file); } ast_str_append(&result, 0, "Content-Type: %s\r\n" "Content-length: %d\r\n" "\r\n" "%s", route->file->mime_type, (int) strlen(tmp), tmp); if (tmp) { ast_free(tmp); } route = unref_route(route); return result; } out404: *status = 404; *title = strdup("Not Found"); *contentlength = 0; return ast_http_error(404, "Not Found", NULL, "Nothing to see here. Move along."); out500: route = unref_route(route); *status = 500; *title = strdup("Internal Server Error"); *contentlength = 0; return ast_http_error(500, "Internal Error", NULL, "An internal error has occured."); } /*! \brief Build a route structure and add it to the list of available http routes \param pp_file File to link to the route \param user User to link to the route (NULL means static route) \param uri URI of the route */ static void build_route(struct phoneprov_file *pp_file, struct user *user, char *uri) { struct http_route *route; if (!(route = ao2_alloc(sizeof(*route), route_destructor))) { return; } if (ast_string_field_init(route, 32)) { ast_log(LOG_ERROR, "Couldn't create string fields for %s\n", pp_file->format); route = unref_route(route); return; } ast_string_field_set(route, uri, S_OR(uri, pp_file->format)); route->user = user; route->file = pp_file; ao2_link(http_routes, route); route = unref_route(route); } /*! \brief Build a phone profile and add it to the list of phone profiles \param name the name of the profile \param v ast_variable from parsing phoneprov.conf */ static void build_profile(const char *name, struct ast_variable *v) { struct phone_profile *profile; struct ast_var_t *var; if (!(profile = ao2_alloc(sizeof(*profile), profile_destructor))) { return; } if (ast_string_field_init(profile, 32)) { profile = unref_profile(profile); return; } if (!(profile->headp = ast_calloc(1, sizeof(*profile->headp)))) { profile = unref_profile(profile); return; } AST_LIST_HEAD_INIT_NOLOCK(&profile->static_files); AST_LIST_HEAD_INIT_NOLOCK(&profile->dynamic_files); ast_string_field_set(profile, name, name); for (; v; v = v->next) { if (!strcasecmp(v->name, "mime_type")) { ast_string_field_set(profile, default_mime_type, v->value); } else if (!strcasecmp(v->name, "setvar")) { struct ast_var_t *variable; char *value_copy = ast_strdupa(v->value); AST_DECLARE_APP_ARGS(args, AST_APP_ARG(varname); AST_APP_ARG(varval); ); AST_NONSTANDARD_APP_ARGS(args, value_copy, '='); do { if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval)) break; args.varname = ast_strip(args.varname); args.varval = ast_strip(args.varval); if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval)) break; if ((variable = ast_var_assign(args.varname, args.varval))) AST_LIST_INSERT_TAIL(profile->headp, variable, entries); } while (0); } else if (!strcasecmp(v->name, "staticdir")) { ast_string_field_set(profile, staticdir, v->value); } else { struct phoneprov_file *pp_file; char *file_extension; char *value_copy = ast_strdupa(v->value); AST_DECLARE_APP_ARGS(args, AST_APP_ARG(filename); AST_APP_ARG(mimetype); ); if (!(pp_file = ast_calloc(1, sizeof(*pp_file)))) { profile = unref_profile(profile); return; } if (ast_string_field_init(pp_file, 32)) { ast_free(pp_file); profile = unref_profile(profile); return; } if ((file_extension = strrchr(pp_file->format, '.'))) file_extension++; AST_STANDARD_APP_ARGS(args, value_copy); /* Mime type order of preference * 1) Specific mime-type defined for file in profile * 2) Mime determined by extension * 3) Default mime type specified in profile * 4) text/plain */ ast_string_field_set(pp_file, mime_type, S_OR(args.mimetype, (S_OR(S_OR(ftype2mtype(file_extension), profile->default_mime_type), "text/plain")))); if (!strcasecmp(v->name, "static_file")) { ast_string_field_set(pp_file, format, args.filename); ast_string_field_build(pp_file, template, "%s%s", profile->staticdir, args.filename); AST_LIST_INSERT_TAIL(&profile->static_files, pp_file, entry); /* Add a route for the static files, as their filenames won't change per-user */ build_route(pp_file, NULL, NULL); } else { ast_string_field_set(pp_file, format, v->name); ast_string_field_set(pp_file, template, args.filename); AST_LIST_INSERT_TAIL(&profile->dynamic_files, pp_file, entry); } } } /* Append the global variables to the variables list for this profile. * This is for convenience later, when we need to provide a single * variable list for use in substitution. */ ast_mutex_lock(&globals_lock); AST_LIST_TRAVERSE(&global_variables, var, entries) { struct ast_var_t *new_var; if ((new_var = ast_var_assign(var->name, var->value))) { AST_LIST_INSERT_TAIL(profile->headp, new_var, entries); } } ast_mutex_unlock(&globals_lock); ao2_link(profiles, profile); profile = unref_profile(profile); } static struct extension *delete_extension(struct extension *exten) { struct ast_var_t *var; while ((var = AST_LIST_REMOVE_HEAD(exten->headp, entries))) { ast_var_delete(var); } ast_free(exten->headp); ast_string_field_free_memory(exten); ast_free(exten); return NULL; } static struct extension *build_extension(struct ast_config *cfg, const char *name) { struct extension *exten; struct ast_var_t *var; const char *tmp; int i; if (!(exten = ast_calloc(1, sizeof(*exten)))) { return NULL; } if (ast_string_field_init(exten, 32)) { ast_free(exten); exten = NULL; return NULL; } ast_string_field_set(exten, name, name); if (!(exten->headp = ast_calloc(1, sizeof(*exten->headp)))) { ast_free(exten); exten = NULL; return NULL; } for (i = 0; i < PP_VAR_LIST_LENGTH; i++) { tmp = ast_variable_retrieve(cfg, name, pp_variable_list[i].user_var); /* If we didn't get a USERNAME variable, set it to the user->name */ if (i == PP_USERNAME && !tmp) { if ((var = ast_var_assign(pp_variable_list[PP_USERNAME].template_var, exten->name))) { AST_LIST_INSERT_TAIL(exten->headp, var, entries); } continue; } else if (i == PP_TIMEZONE) { /* perfectly ok if tmp is NULL, will set variables based on server's time zone */ set_timezone_variables(exten->headp, tmp); } else if (i == PP_LINENUMBER) { if (!tmp) { tmp = "1"; } exten->index = atoi(tmp); } if (tmp && (var = ast_var_assign(pp_variable_list[i].template_var, tmp))) { AST_LIST_INSERT_TAIL(exten->headp, var, entries); } } if (!ast_strlen_zero(global_server)) { if ((var = ast_var_assign("SERVER", global_server))) AST_LIST_INSERT_TAIL(exten->headp, var, entries); } if (!ast_strlen_zero(global_serverport)) { if ((var = ast_var_assign("SERVER_PORT", global_serverport))) AST_LIST_INSERT_TAIL(exten->headp, var, entries); } return exten; } static struct user *unref_user(struct user *user) { ao2_ref(user, -1); return NULL; } /*! \brief Return a user looked up by name */ static struct user *find_user(const char *macaddress) { struct user tmp = { .macaddress = macaddress, }; return ao2_find(users, &tmp, OBJ_POINTER); } static int users_hash_fn(const void *obj, const int flags) { const struct user *user = obj; return ast_str_hash(user->macaddress); } static int users_cmp_fn(void *obj, void *arg, int flags) { const struct user *user1 = obj, *user2 = arg; return !strcasecmp(user1->macaddress, user2->macaddress) ? CMP_MATCH | CMP_STOP : 0; } /*! \brief Free all memory associated with a user */ static void user_destructor(void *obj) { struct user *user = obj; struct extension *exten; while ((exten = AST_LIST_REMOVE_HEAD(&user->extensions, entry))) { exten = delete_extension(exten); } if (user->profile) { user->profile = unref_profile(user->profile); } ast_string_field_free_memory(user); } /*! \brief Delete all users */ static void delete_users(void) { struct ao2_iterator i; struct user *user; i = ao2_iterator_init(users, 0); while ((user = ao2_iterator_next(&i))) { ao2_unlink(users, user); user = unref_user(user); } } /*! \brief Build and return a user structure based on gathered config data */ static struct user *build_user(const char *mac, struct phone_profile *profile) { struct user *user; if (!(user = ao2_alloc(sizeof(*user), user_destructor))) { profile = unref_profile(profile); return NULL; } if (ast_string_field_init(user, 32)) { profile = unref_profile(profile); user = unref_user(user); return NULL; } ast_string_field_set(user, macaddress, mac); user->profile = profile; /* already ref counted by find_profile */ return user; } /*! \brief Add an extension to a user ordered by index/linenumber */ static int add_user_extension(struct user *user, struct extension *exten) { struct ast_var_t *var; /* Append profile variables here, and substitute variables on profile * setvars, so that we can use user specific variables in them */ AST_LIST_TRAVERSE(user->profile->headp, var, entries) { char expand_buf[VAR_BUF_SIZE] = {0,}; struct ast_var_t *var2; pbx_substitute_variables_varshead(exten->headp, var->value, expand_buf, sizeof(expand_buf)); if ((var2 = ast_var_assign(var->name, expand_buf))) AST_LIST_INSERT_TAIL(exten->headp, var2, entries); } if (AST_LIST_EMPTY(&user->extensions)) { AST_LIST_INSERT_HEAD(&user->extensions, exten, entry); } else { struct extension *exten_iter; AST_LIST_TRAVERSE_SAFE_BEGIN(&user->extensions, exten_iter, entry) { if (exten->index < exten_iter->index) { AST_LIST_INSERT_BEFORE_CURRENT(exten, entry); } else if (exten->index == exten_iter->index) { ast_log(LOG_WARNING, "Duplicate linenumber=%d for %s\n", exten->index, user->macaddress); return -1; } else if (!AST_LIST_NEXT(exten_iter, entry)) { AST_LIST_INSERT_TAIL(&user->extensions, exten, entry); } } AST_LIST_TRAVERSE_SAFE_END; } return 0; } /*! \brief Add an http route for dynamic files attached to the profile of the user */ static int build_user_routes(struct user *user) { struct phoneprov_file *pp_file; AST_LIST_TRAVERSE(&user->profile->dynamic_files, pp_file, entry) { char expand_buf[VAR_BUF_SIZE] = { 0, }; pbx_substitute_variables_varshead(AST_LIST_FIRST(&user->extensions)->headp, pp_file->format, expand_buf, sizeof(expand_buf)); build_route(pp_file, user, expand_buf); } return 0; } /* \brief Parse config files and create appropriate structures */ static int set_config(void) { struct ast_config *cfg, *phoneprov_cfg; char *cat; struct ast_variable *v; struct ast_flags config_flags = { 0 }; struct ast_var_t *var; /* Try to grab the port from sip.conf. If we don't get it here, we'll set it * to whatever is set in phoneprov.conf or default to 5060 */ if ((cfg = ast_config_load("sip.conf", config_flags))) { ast_copy_string(global_serverport, S_OR(ast_variable_retrieve(cfg, "general", "bindport"), "5060"), sizeof(global_serverport)); ast_config_destroy(cfg); } if (!(cfg = ast_config_load("users.conf", config_flags))) { ast_log(LOG_WARNING, "Unable to load users.conf\n"); return 0; } /* Go ahead and load global variables from users.conf so we can append to profiles */ for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { if (!strcasecmp(v->name, "vmexten")) { if ((var = ast_var_assign("VOICEMAIL_EXTEN", v->value))) { ast_mutex_lock(&globals_lock); AST_LIST_INSERT_TAIL(&global_variables, var, entries); ast_mutex_unlock(&globals_lock); } } if (!strcasecmp(v->name, "localextenlength")) { if ((var = ast_var_assign("EXTENSION_LENGTH", v->value))) ast_mutex_lock(&globals_lock); AST_LIST_INSERT_TAIL(&global_variables, var, entries); ast_mutex_unlock(&globals_lock); } } if (!(phoneprov_cfg = ast_config_load("phoneprov.conf", config_flags))) { ast_log(LOG_ERROR, "Unable to load config phoneprov.conf\n"); ast_config_destroy(cfg); return -1; } cat = NULL; while ((cat = ast_category_browse(phoneprov_cfg, cat))) { if (!strcasecmp(cat, "general")) { for (v = ast_variable_browse(phoneprov_cfg, cat); v; v = v->next) { if (!strcasecmp(v->name, "serveraddr")) ast_copy_string(global_server, v->value, sizeof(global_server)); else if (!strcasecmp(v->name, "serveriface")) { struct in_addr addr; lookup_iface(v->value, &addr); ast_copy_string(global_server, ast_inet_ntoa(addr), sizeof(global_server)); } else if (!strcasecmp(v->name, "serverport")) ast_copy_string(global_serverport, v->value, sizeof(global_serverport)); else if (!strcasecmp(v->name, "default_profile")) ast_copy_string(global_default_profile, v->value, sizeof(global_default_profile)); } } else build_profile(cat, ast_variable_browse(phoneprov_cfg, cat)); } ast_config_destroy(phoneprov_cfg); cat = NULL; while ((cat = ast_category_browse(cfg, cat))) { const char *tmp, *mac; struct user *user; struct phone_profile *profile; struct extension *exten; if (!strcasecmp(cat, "general")) { continue; } if (!strcasecmp(cat, "authentication")) continue; if (!((tmp = ast_variable_retrieve(cfg, cat, "autoprov")) && ast_true(tmp))) continue; if (!(mac = ast_variable_retrieve(cfg, cat, "macaddress"))) { ast_log(LOG_WARNING, "autoprov set for %s, but no mac address - skipping.\n", cat); continue; } tmp = S_OR(ast_variable_retrieve(cfg, cat, "profile"), global_default_profile); if (ast_strlen_zero(tmp)) { ast_log(LOG_WARNING, "No profile for user [%s] with mac '%s' - skipping\n", cat, mac); continue; } if (!(user = find_user(mac))) { if (!(profile = find_profile(tmp))) { ast_log(LOG_WARNING, "Could not look up profile '%s' - skipping.\n", tmp); continue; } if (!(user = build_user(mac, profile))) { ast_log(LOG_WARNING, "Could not create user for '%s' - skipping\n", user->macaddress); continue; } if (!(exten = build_extension(cfg, cat))) { ast_log(LOG_WARNING, "Could not create extension for %s - skipping\n", user->macaddress); user = unref_user(user); continue; } if (add_user_extension(user, exten)) { ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress); user = unref_user(user); exten = delete_extension(exten); continue; } if (build_user_routes(user)) { ast_log(LOG_WARNING, "Could not create http routes for %s - skipping\n", user->macaddress); user = unref_user(user); continue; } ao2_link(users, user); user = unref_user(user); } else { if (!(exten = build_extension(cfg, cat))) { ast_log(LOG_WARNING, "Could not create extension for %s - skipping\n", user->macaddress); user = unref_user(user); continue; } if (add_user_extension(user, exten)) { ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress); user = unref_user(user); exten = delete_extension(exten); continue; } user = unref_user(user); } } ast_config_destroy(cfg); return 0; } /*! \brief Delete all http routes, freeing their memory */ static void delete_routes(void) { struct ao2_iterator i; struct http_route *route; i = ao2_iterator_init(http_routes, 0); while ((route = ao2_iterator_next(&i))) { ao2_unlink(http_routes, route); route = unref_route(route); } } /*! \brief Delete all phone profiles, freeing their memory */ static void delete_profiles(void) { struct ao2_iterator i; struct phone_profile *profile; i = ao2_iterator_init(profiles, 0); while ((profile = ao2_iterator_next(&i))) { ao2_unlink(profiles, profile); profile = unref_profile(profile); } } /*! \brief A dialplan function that can be used to print a string for each phoneprov user */ static int pp_each_user_exec(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) { char *tmp, expand_buf[VAR_BUF_SIZE] = {0,}; struct ao2_iterator i; struct user *user; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(string); AST_APP_ARG(exclude_mac); ); AST_STANDARD_APP_ARGS(args, data); /* Fix data by turning %{ into ${ */ while ((tmp = strstr(args.string, "%{"))) *tmp = '$'; i = ao2_iterator_init(users, 0); while ((user = ao2_iterator_next(&i))) { if (!ast_strlen_zero(args.exclude_mac) && !strcasecmp(user->macaddress, args.exclude_mac)) { continue; } pbx_substitute_variables_varshead(AST_LIST_FIRST(&user->extensions)->headp, args.string, expand_buf, sizeof(expand_buf)); ast_build_string(&buf, &len, "%s", expand_buf); user = unref_user(user); } return 0; } static struct ast_custom_function pp_each_user_function = { .name = "PP_EACH_USER", .synopsis = "Generate a string for each phoneprov user", .syntax = "PP_EACH_USER(|)", .desc = "Pass in a string, with phoneprov variables you want substituted in the format of\n" "%{VARNAME}, and you will get the string rendered for each user in phoneprov\n" "excluding ones with MAC address . Probably not useful outside of\n" "res_phoneprov.\n" "\nExample: ${PP_EACH_USER(%{DISPLAY_NAME}|${MAC})", .read = pp_each_user_exec, }; /*! \brief A dialplan function that can be used to output a template for each extension attached to a user */ static int pp_each_extension_exec(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) { struct user *user; struct extension *exten; char path[PATH_MAX]; char *file; int filelen; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(mac); AST_APP_ARG(template); ); AST_STANDARD_APP_ARGS(args, data); if (ast_strlen_zero(args.mac) || ast_strlen_zero(args.template)) { ast_log(LOG_WARNING, "PP_EACH_EXTENSION requries both a macaddress and template filename.\n"); return 0; } if (!(user = find_user(args.mac))) { ast_log(LOG_WARNING, "Could not find user with mac = '%s'\n", args.mac); return 0; } snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, args.template); filelen = load_file(path, &file); if (filelen < 0) { ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, filelen); if (file) { ast_free(file); } return 0; } if (!file) { return 0; } AST_LIST_TRAVERSE(&user->extensions, exten, entry) { char expand_buf[VAR_BUF_SIZE] = {0,}; pbx_substitute_variables_varshead(exten->headp, file, expand_buf, sizeof(expand_buf)); ast_build_string(&buf, &len, "%s", expand_buf); } ast_free(file); user = unref_user(user); return 0; } static struct ast_custom_function pp_each_extension_function = { .name = "PP_EACH_EXTENSION", .synopsis = "Execute specified template for each extension", .syntax = "PP_EACH_EXTENSION(|