mirror of
https://github.com/asterisk/asterisk.git
synced 2026-03-19 03:54:04 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
869e8bc579 | ||
|
|
8bc24fabfa | ||
|
|
d7326592f2 | ||
|
|
7f269f6735 |
5
BUGS
5
BUGS
@@ -1,8 +1,3 @@
|
||||
Asterisk 1.0-RC-1 Known Major Bugs
|
||||
==================================
|
||||
* Some people still have issues with H.323
|
||||
* QuickNet driver still not entirely stable
|
||||
|
||||
Asterisk Bug Tracking Information
|
||||
=================================
|
||||
|
||||
|
||||
168
CHANGES
168
CHANGES
@@ -1,171 +1,3 @@
|
||||
NOTE: Corrections or additions to the ChangeLog may be submitted
|
||||
to http://bugs.digium.com. Documentation and formatting
|
||||
fixes are not listed here. A complete listing of changes
|
||||
is available through the Asterisk-CVS mailing list hosted
|
||||
at http://lists.digium.com.
|
||||
|
||||
Asterisk 1.0.6
|
||||
|
||||
-- chan_iax2:
|
||||
-- Fixed a bug dealing with a division by zero that could cause a crash
|
||||
-- chan_sip:
|
||||
-- Behavior was changed so that when a registration fails due to DNS resolution issues,
|
||||
a retry will be attempted in 20 seconds.
|
||||
-- Peer settings were not reset to null values when reloading the configuration file.
|
||||
Behavior has been changed so that these values are now cleared.
|
||||
-- 'restrictcid' now properly works on MySQL peers.
|
||||
-- Only use the default callerid if it has been specified.
|
||||
-- Asterisk was not sending the same From: line in SIP messages during certain times.
|
||||
Fixed to make sure it stays the same. This makes some providers happier, to a working state.
|
||||
-- Certain circumstances involving a blank callerid caused asterisk to segmentation fault.
|
||||
-- There was a problem incorrectly matching codec availablity when global preferences were
|
||||
different from that of the user. To fix this, processing of SDP data has been moved
|
||||
to after determining who the call is coming from.
|
||||
-- Asterisk would run out of RTP ports while waiting for SUBSCRIBE's to expire even though
|
||||
an RTP port isn't needed in this case. This has been fixed by releasing the ports early.
|
||||
-- chan_zap:
|
||||
-- During a certain scenario when using flash and '#' transfers you would hear the
|
||||
other person and the music they were hearing. This has been fixed.
|
||||
-- A fix for a compilation issue with gcc4 was added.
|
||||
-- chan_modem_bestdata:
|
||||
-- A fix for a compilation issue with gcc4 was added.
|
||||
-- format_g729:
|
||||
-- Treat a 10-byte read as an end of file indication instead of an error. Some G729 encoders
|
||||
like to put 10-bytes at the end to indicate this.
|
||||
-- res_features:
|
||||
-- During certain situations when parking a call, both endpoints would get musiconhold.
|
||||
This has been fixed so the individual who parked the call will hear the digits and not
|
||||
musiconhold.
|
||||
-- app_dial:
|
||||
-- DIALEDPEERNUMBER is now being set, so if you attempted to use it in the past and failed
|
||||
it should work now.
|
||||
-- A callerid change caused many headaches, this has been reversed to the original 1.0 behavior.
|
||||
-- A crash caused with the combination of the 'g' option and # transfer was fixed.
|
||||
-- app_voicemail:
|
||||
-- If two people hit the voicemail system at the same time, and were leaving a message
|
||||
the second message was overwriting the first. This has been fixed so that each one
|
||||
is distinct and will not overwrite eachother.
|
||||
-- cdr_tds:
|
||||
-- If the server you were using was going down, it had the potential to bring your asterisk
|
||||
server down with it. Extra stuff has been added so as to bring in more error/connection
|
||||
checking.
|
||||
-- cdr_pgsql:
|
||||
-- This will now attempt to reconnect after a connection problem.
|
||||
-- IAXY firmware:
|
||||
-- This has been updated to version 23. It includes a fix for lost registrations.
|
||||
-- internals
|
||||
-- Behavior was changed for 'show codec <number>' to make it more intuitive. (kshumard)
|
||||
-- DNS failures and asterisk do not get along too well, this is not totally the case anymore.
|
||||
-- Asterisk will now handle DNS failures at startup more gracefully, and won't crash and
|
||||
burn.
|
||||
-- Choosing to append to a wave file would render the outputted wave file corrupt. Appending
|
||||
now works again.
|
||||
-- If you failed to define certain keys, asterisk had the potential to crash when seeing if you had
|
||||
used them.
|
||||
-- Attempting to use such things as ${EXTEN:-1} gave a wrong return value. However, this was never
|
||||
a documented feature...
|
||||
|
||||
Asterisk 1.0.5
|
||||
|
||||
-- chan_zap
|
||||
-- fix a callerid bug introduced in 1.0.4
|
||||
-- app_queue
|
||||
-- fix some penalty behavior
|
||||
|
||||
Asterisk 1.0.4
|
||||
|
||||
-- general
|
||||
-- fix memory leak evident with extensive use of variables
|
||||
-- update IAXy firmware to version 22
|
||||
-- enable some special write protection
|
||||
-- enable outbound DTMF
|
||||
-- fix seg fault with incorrect usage of SetVar
|
||||
-- other minor fixes including typos and doc updates
|
||||
-- chan_sip
|
||||
-- fix codecs to not be case sensitive
|
||||
-- Re-use auth credentials
|
||||
-- fix MWI when using type=friend
|
||||
-- fix global NAT option
|
||||
-- chan_agent / chan_local
|
||||
-- fix incorrect use count
|
||||
-- chan_zap
|
||||
-- Allow CID rings to be configured in zapata.conf
|
||||
-- no more patching needed for UK CID
|
||||
-- app_macro
|
||||
-- allow Macros to exit with '*' or '#' like regular extension processing
|
||||
-- app_voicemail
|
||||
-- don't allow '#' as a password
|
||||
-- add option to save voicemail before going to the operator
|
||||
-- fix global operator=yes
|
||||
-- app_read
|
||||
-- return 0 instead of -1 if user enters nothing
|
||||
-- res_agi
|
||||
-- don't exit AGI when file not found to stream
|
||||
-- send script parameter when using FastAGI
|
||||
|
||||
Asterisk 1.0.3
|
||||
|
||||
-- chan_zap
|
||||
-- fix seg fault when doing *0 to flash a trunk
|
||||
-- rtp
|
||||
-- seg fault fix
|
||||
-- chan_sip
|
||||
-- fix to prevent seg fault when attempting a transfer
|
||||
-- fix bug with supervised transfers
|
||||
-- fix codec preferences
|
||||
-- chan_h323
|
||||
-- fix compilation problem
|
||||
-- chan_iax2
|
||||
-- avoid a deadlock related to a static config of a BUNCH of peers
|
||||
-- cdr_pgsql
|
||||
-- fix memory leak when reading config
|
||||
-- Numerous other minor bug fixes
|
||||
|
||||
Asterisk 1.0.2
|
||||
|
||||
-- Major bugfix release
|
||||
|
||||
Asterisk 1.0.1
|
||||
|
||||
-- Added AGI over TCP support
|
||||
-- Add ability to purge callers from queue if no agents are logged in
|
||||
-- Fix inband PRI indication detection
|
||||
-- Fix for MGCP - always request digits if no RTP stream
|
||||
-- Fixed seg fault for ast_control_streamfile
|
||||
-- Make pick-up extension configurable via features.conf
|
||||
-- Numerous other bug fixes
|
||||
|
||||
Asterisk 1.0.0
|
||||
-- Use Q.931 standard cause codes for asterisk cause codes
|
||||
-- Bug fixes from the bug tracker
|
||||
Asterisk 1.0-RC2
|
||||
-- Additional CDR backends
|
||||
-- Allow muted to reconnect
|
||||
-- Call parking improvements (including SIP parking support)
|
||||
-- Added licensed hold music from FreePlayMusic
|
||||
-- GR-303 and Zap improvements
|
||||
-- More bug fixes from the bug tracker
|
||||
-- Improved FreeBSD/OpenBSD/MacOS X support
|
||||
Asterisk 1.0-RC1
|
||||
-- Innumerable bug fixes and features from the bug tracker
|
||||
-- Added Open Settlement Protocol (OSP) support
|
||||
-- Added Non-facility Associated Signalling (NFAS) Support
|
||||
-- Added alarm Monitoring support
|
||||
-- Added new MeetMe options
|
||||
-- Added GR-303 Support
|
||||
-- Added trunk groups
|
||||
-- ADPCM Standardization
|
||||
-- Numerous bug fixes
|
||||
-- Add IAX2 Firmware Support
|
||||
-- Add G.726 support
|
||||
-- Add ices/icecast support
|
||||
-- Numerous bug fixes
|
||||
Asterisk 0.7.2
|
||||
-- Countless small bug fixes from bug tracker
|
||||
-- DSP Fixes
|
||||
-- Fix unloading of Zaptel
|
||||
-- Pass Caller*ID/ANI properly on call forwarding
|
||||
-- Add indication for Italy
|
||||
Asterisk 0.7.1
|
||||
-- Fixed timed include context's and GotoIfTime
|
||||
-- Fixed chan_h323 it now gets remote ip properly instead of 127.0.0.1
|
||||
|
||||
11
CREDITS
11
CREDITS
@@ -5,8 +5,6 @@ Asterisk:
|
||||
|
||||
Pilosoft, Inc. - for supporting ADSI development in Asterisk
|
||||
|
||||
Asterlink, Inc. - for supporting broad Asterisk development
|
||||
|
||||
GFS - for supporting ALSA development
|
||||
|
||||
Telesthetic - for supporting SIP development
|
||||
@@ -14,7 +12,6 @@ Telesthetic - for supporting SIP development
|
||||
Christos Ricudis - for substantial code contributions
|
||||
|
||||
Paul Bagyenda, Digital Solutions - for initial Voicetronix driver development
|
||||
|
||||
=== WISHLIST CONTRIBUTERS ===
|
||||
Jeremy McNamara - SpeeX support
|
||||
Nick Seraphin - RDNIS support
|
||||
@@ -26,8 +23,6 @@ Wasim - Hangup detect
|
||||
PhoneJack and Linejack card to the project. (http://www.quicknet.net)
|
||||
|
||||
=== MISCELLANEOUS PATCHES ===
|
||||
Anthony Minessale - Countless big and small fixes, and relentless forward push
|
||||
anthmct@yahoo.com http://www.asterlink.com
|
||||
James Golovich - Innumerable contributions
|
||||
You can find him and asterisk-perl at http://asterisk.gnuinter.net
|
||||
Andre Bierwirth - Extension hints and status
|
||||
@@ -58,15 +53,11 @@ Thorsten Lockert - OpenBSD, FreeBSD ports, making MacOS X port run on 10.3,
|
||||
bugs. tholo@sigmasoft.com
|
||||
Brian West - ODBC support and Bug Marshaling
|
||||
William Waites - syslog support, SIP NAT traversal for SIP-UA. ww@styx.org
|
||||
Rich Murphey - Porting to FreeBSD, NetBSD, OpenBSD, and Darwin.
|
||||
rich@whiteoaklabs.com http://whiteoaklabs.com
|
||||
|
||||
|
||||
=== OTHER CONTRIBUTIONS ===
|
||||
John Todd - Monkey sounds and associated teletorture prompt
|
||||
|
||||
=== HOLD MUSIC ===
|
||||
Music provided by www.opsound.org
|
||||
|
||||
=== OTHER SOURCE CODE IN ASTERISK ===
|
||||
|
||||
I did not implement the codecs in asterisk. Here is the copyright on the
|
||||
|
||||
6
HARDWARE
6
HARDWARE
@@ -16,11 +16,11 @@ Zaptel compatible hardware
|
||||
* Wildcard X100P - Single FXO interface connects to Loopstart phone
|
||||
line
|
||||
|
||||
* Wildcard T400P (obsolete) - Quad T1 interface connects to four T1/PRI
|
||||
* Wildcard T400P - Quad T1 interface connects to four T1/PRI
|
||||
interfaces. Supports RBS and PRI voice and PPP, FR, and HDLC data.
|
||||
|
||||
* Wildcard E400P (obsolete)- Quad E1 interface connects to four E1/PRI
|
||||
(or PRA) interfaces. Supports PRA/PRI, EuroISDN voice and data.
|
||||
* Wildcard E400P - Quad E1 interface connects to four E1/PRI (or PRA)
|
||||
interfaces. Supports PRA/PRI, EuroISDN voice and PPP, FR, HDLC data.
|
||||
|
||||
* Wildcard T100P - Single T1 interface connects to a single T1/PRI
|
||||
interface. Supports RBS and PRI voice and PPP, FR, and HDLC data.
|
||||
|
||||
168
Makefile
168
Makefile
@@ -20,31 +20,11 @@ OSARCH=$(shell uname -s)
|
||||
|
||||
ifeq (${OSARCH},Linux)
|
||||
PROC=$(shell uname -m)
|
||||
ifeq ($(PROC),x86_64)
|
||||
# You must have GCC 3.4 to use k8, otherwise use athlon
|
||||
PROC=k8
|
||||
#PROC=athlon
|
||||
OPTIONS+=-m64
|
||||
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
|
||||
|
||||
MPG123TARG=linux
|
||||
endif
|
||||
|
||||
ifeq ($(findstring BSD,${OSARCH}),BSD)
|
||||
else
|
||||
ifeq (${OSARCH},FreeBSD)
|
||||
PROC=$(shell uname -m)
|
||||
endif
|
||||
|
||||
endif
|
||||
# Pentium Pro Optimize
|
||||
#PROC=i686
|
||||
|
||||
@@ -63,18 +43,15 @@ PWD=$(shell pwd)
|
||||
#K6OPT = -DK6OPT
|
||||
|
||||
#Tell gcc to optimize the asterisk's code
|
||||
OPTIMIZE+=-O6
|
||||
OPTIMIZE=-O6
|
||||
|
||||
#Include debug symbols in the executables (-g) and profiling info (-pg)
|
||||
DEBUG=-g #-pg
|
||||
|
||||
# If you are running a radio application, define RADIO_RELAX so that the DTMF
|
||||
# will be received more reliably
|
||||
#OPTIONS += -DRADIO_RELAX
|
||||
|
||||
# If you don't have a lot of memory (e.g. embedded Asterisk), uncomment the
|
||||
# following to reduce the size of certain static buffers
|
||||
#OPTIONS += -DLOW_MEMORY
|
||||
# New hangup routines for chan_zap.c
|
||||
# If this flag is uncommented then you need to have new libpri code in your system
|
||||
# You can still use the old libpri if you do "cvs update -D "08/03/03" in libpri source code
|
||||
OPTIONS += -DNEW_PRI_HANGUP
|
||||
|
||||
# Optional debugging parameters
|
||||
DEBUG_THREADS = #-DDEBUG_THREADS #-DDO_CRASH
|
||||
@@ -121,7 +98,6 @@ ASTCONFPATH=$(ASTETCDIR)/asterisk.conf
|
||||
ASTBINDIR=$(INSTALL_PREFIX)/usr/bin
|
||||
ASTSBINDIR=$(INSTALL_PREFIX)/usr/sbin
|
||||
ASTVARRUNDIR=$(INSTALL_PREFIX)/var/run
|
||||
ASTMANDIR=$(INSTALL_PREFIX)/usr/share/man
|
||||
|
||||
MODULES_DIR=$(ASTLIBDIR)/modules
|
||||
AGI_DIR=$(ASTVARLIBDIR)/agi-bin
|
||||
@@ -129,29 +105,12 @@ AGI_DIR=$(ASTVARLIBDIR)/agi-bin
|
||||
INCLUDE=-Iinclude -I../include
|
||||
CFLAGS=-pipe -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations $(DEBUG) $(INCLUDE) -D_REENTRANT -D_GNU_SOURCE #-DMAKE_VALGRIND_HAPPY
|
||||
CFLAGS+=$(OPTIMIZE)
|
||||
|
||||
ifneq ($(PROC),ultrasparc)
|
||||
CFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi)
|
||||
endif
|
||||
|
||||
CFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi)
|
||||
CFLAGS+=$(shell if [ -f /usr/include/osp/osp.h ]; then echo "-DOSP_SUPPORT -I/usr/include/osp" ; fi)
|
||||
|
||||
ifeq (${OSARCH},FreeBSD)
|
||||
OSVERSION=$(shell make -V OSVERSION -f /usr/share/mk/bsd.port.subdir.mk)
|
||||
CFLAGS+=$(shell if test ${OSVERSION} -lt 500016 ; then echo "-D_THREAD_SAFE"; fi)
|
||||
LIBS+=$(shell if test ${OSVERSION} -lt 502102 ; then echo "-lc_r"; else echo "-pthread"; fi)
|
||||
INCLUDE+=-I/usr/local/include
|
||||
CFLAGS+=$(shell if [ -d /usr/local/include/spandsp ]; then echo "-I/usr/local/include/spandsp"; fi)
|
||||
MPG123TARG=freebsd
|
||||
endif # FreeBSD
|
||||
|
||||
ifeq (${OSARCH},NetBSD)
|
||||
CFLAGS+=-pthread
|
||||
INCLUDE+=-I/usr/local/include -I/usr/pkg/include
|
||||
MPG123TARG=netbsd
|
||||
INCLUDE+=-I/usr/local/include
|
||||
endif
|
||||
|
||||
ifeq (${OSARCH},OpenBSD)
|
||||
CFLAGS+=-pthread
|
||||
endif
|
||||
@@ -160,11 +119,10 @@ endif
|
||||
#CFLAGS+=-DOLD_DSP_ROUTINES
|
||||
|
||||
CFLAGS+=$(shell if [ -f /usr/include/linux/zaptel.h ]; then echo "-DZAPTEL_OPTIMIZATIONS"; fi)
|
||||
CFLAGS+=$(shell if [ -f /usr/local/include/zaptel.h ]; then echo "-DZAPTEL_OPTIMIZATIONS"; fi)
|
||||
|
||||
LIBEDIT=editline/libedit.a
|
||||
|
||||
ASTERISKVERSION=$(shell if [ -f .version ]; then cat .version; else if [ -d CVS ]; then if [ -f CVS/Tag ] ; then echo "CVS-`sed 's/^T//g' CVS/Tag`-`date +"%D-%T"`"; else echo "CVS-HEAD-`date +"%D-%T"`"; fi; fi; fi)
|
||||
ASTERISKVERSION=$(shell if [ -f .version ]; then cat .version; else if [ -d CVS ]; then echo "CVS-`date +"%D-%T"`"; fi; fi)
|
||||
HTTPDIR=$(shell if [ -d /var/www ]; then echo "/var/www"; else echo "/home/httpd"; fi)
|
||||
RPMVERSION=$(shell if [ -f .version ]; then sed 's/[-\/:]/_/g' .version; else echo "unknown" ; fi)
|
||||
CFLAGS+=-DASTERISK_VERSION=\"$(ASTERISKVERSION)\"
|
||||
@@ -189,30 +147,29 @@ SUBDIRS=res channels pbx apps codecs formats agi cdr astman stdtime
|
||||
ifeq (${OSARCH},Linux)
|
||||
LIBS=-ldl -lpthread
|
||||
endif
|
||||
ifeq (${OSARCH},OpenBSD)
|
||||
LIBS=-pthread
|
||||
else
|
||||
ifeq (${OSARCH},FreeBSD)
|
||||
LIBS=-pthread
|
||||
else
|
||||
endif
|
||||
endif
|
||||
LIBS+=-lncurses -lm
|
||||
ifeq (${OSARCH},Linux)
|
||||
LIBS+=-lresolv #-lnjamd
|
||||
endif
|
||||
ifeq (${OSARCH},Darwin)
|
||||
ifeq ($(shell uname -r),7.0.0)
|
||||
LIBS+=-lresolv
|
||||
endif
|
||||
ifeq (${OSARCH},FreeBSD)
|
||||
LIBS+=-lcrypto
|
||||
endif
|
||||
ifeq (${OSARCH},NetBSD)
|
||||
LIBS+=-lpthread -lcrypto -lm -L/usr/local/lib -L/usr/pkg/lib -lncurses
|
||||
endif
|
||||
ifeq (${OSARCH},OpenBSD)
|
||||
LIBS=-lcrypto -lpthread -lm -lncurses
|
||||
endif
|
||||
LIBS+=-lssl
|
||||
OBJS=io.o sched.o logger.o frame.o loader.o config.o channel.o \
|
||||
translate.o file.o say.o pbx.o cli.o md5.o term.o \
|
||||
ulaw.o alaw.o callerid.o fskmodem.o image.o app.o \
|
||||
cdr.o tdd.o acl.o rtp.o manager.o asterisk.o ast_expr.o \
|
||||
dsp.o chanvars.o indications.o autoservice.o db.o privacy.o \
|
||||
astmm.o enum.o srv.o dns.o aescrypt.o aestab.o aeskey.o \
|
||||
utils.o
|
||||
astmm.o enum.o srv.o dns.o aescrypt.o aestab.o aeskey.o
|
||||
ifeq (${OSARCH},Darwin)
|
||||
OBJS+=poll.o dlfcn.o
|
||||
ASTLINK=-Wl,-dynamic
|
||||
@@ -234,7 +191,7 @@ _all: all
|
||||
@echo " + $(MAKE) install +"
|
||||
@echo " +-------------------------------------------+"
|
||||
|
||||
all: depend asterisk subdirs
|
||||
all: depend asterisk subdirs
|
||||
|
||||
editline/config.h:
|
||||
cd editline && unset CFLAGS LIBS && ./configure ; \
|
||||
@@ -271,14 +228,6 @@ cli.o: cli.c build.h
|
||||
|
||||
asterisk.o: asterisk.c build.h
|
||||
|
||||
manpage: asterisk.8.gz
|
||||
|
||||
asterisk.8.gz: asterisk.sgml
|
||||
rm -f asterisk.8
|
||||
docbook2man asterisk.sgml
|
||||
mv ./*.8 asterisk.8
|
||||
gzip asterisk.8
|
||||
|
||||
ifneq ($(strip $(ASTERISKVERSION)),)
|
||||
build.h: .version
|
||||
./make_build_h
|
||||
@@ -296,10 +245,7 @@ stdtime/libtime.a: FORCE
|
||||
fi
|
||||
|
||||
asterisk: editline/libedit.a db1-ast/libdb1.a stdtime/libtime.a $(OBJS)
|
||||
$(CC) $(DEBUG) -o asterisk $(ASTLINK) $(OBJS) $(LIBEDIT) db1-ast/libdb1.a stdtime/libtime.a $(LIBS)
|
||||
|
||||
muted: muted.o
|
||||
$(CC) -o muted muted.o
|
||||
$(CC) $(DEBUG) -o asterisk $(ASTLINK) $(OBJS) $(LIBS) $(LIBEDIT) db1-ast/libdb1.a stdtime/libtime.a
|
||||
|
||||
subdirs:
|
||||
for x in $(SUBDIRS); do $(MAKE) -C $$x || exit 1 ; done
|
||||
@@ -310,7 +256,6 @@ clean:
|
||||
rm -f build.h
|
||||
rm -f ast_expr.c
|
||||
@if [ -e editline/Makefile ]; then $(MAKE) -C editline distclean ; fi
|
||||
@if [ -d mpg123-0.59r ]; then $(MAKE) -C mpg123-0.59r clean; fi
|
||||
$(MAKE) -C db1-ast clean
|
||||
$(MAKE) -C stdtime clean
|
||||
|
||||
@@ -324,25 +269,7 @@ datafiles: all
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/letters
|
||||
for x in sounds/letters/*.gsm; do \
|
||||
if grep -q "^%`basename $$x`%" sounds.txt; then \
|
||||
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds/letters ; \
|
||||
else \
|
||||
echo "No description for $$x"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/phonetic
|
||||
for x in sounds/phonetic/*.gsm; do \
|
||||
if grep -q "^%`basename $$x`%" sounds.txt; then \
|
||||
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds/phonetic ; \
|
||||
else \
|
||||
echo "No description for $$x"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
for x in sounds/vm-* sounds/transfer* sounds/pbx-* sounds/ss-* sounds/beep* sounds/dir-* sounds/conf-* sounds/agent-* sounds/invalid* sounds/tt-* sounds/auth-* sounds/privacy-* sounds/queue-*; do \
|
||||
for x in sounds/vm-* sounds/transfer* sounds/pbx-* sounds/ss-* sounds/beep* sounds/dir-* sounds/conf-* sounds/agent-* sounds/invalid* sounds/tt-* sounds/auth-* sounds/privacy-*; do \
|
||||
if grep -q "^%`basename $$x`%" sounds.txt; then \
|
||||
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds ; \
|
||||
else \
|
||||
@@ -360,7 +287,7 @@ datafiles: all
|
||||
update:
|
||||
@if [ -d CVS ]; then \
|
||||
echo "Updating from CVS..." ; \
|
||||
cvs -q -z3 update -Pd; \
|
||||
cvs -q update -Pd; \
|
||||
rm -f .version; \
|
||||
else \
|
||||
echo "Not CVS"; \
|
||||
@@ -374,7 +301,6 @@ bininstall: all
|
||||
mkdir -p $(DESTDIR)$(ASTSBINDIR)
|
||||
mkdir -p $(DESTDIR)$(ASTVARRUNDIR)
|
||||
mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/voicemail
|
||||
mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/tmp
|
||||
install -m 755 asterisk $(DESTDIR)$(ASTSBINDIR)/
|
||||
install -m 755 contrib/scripts/astgenkey $(DESTDIR)$(ASTSBINDIR)/
|
||||
if [ ! -f $(DESTDIR)$(ASTSBINDIR)/safe_asterisk ]; then \
|
||||
@@ -392,23 +318,19 @@ bininstall: all
|
||||
rm -f $(DESTDIR)$(ASTSPOOLDIR)/vm; \
|
||||
fi
|
||||
ln -s $(ASTSPOOLDIR)/voicemail/default $(DESTDIR)$(ASTSPOOLDIR)/vm
|
||||
rm -f $(DESTDIR)$(MODULES_DIR)/chan_ixj.so
|
||||
rm -f $(DESTDIR)$(MODULES_DIR)/chan_tor.so
|
||||
rm -f $(DESTDIR)$(MODULES_DIR)/cdr_mysql.so
|
||||
rm -f $(DESTDIR)$(MODULES_DIR)/cdr_unixodbc.so
|
||||
rm -f $(DESTDIR)$(MODULES_DIR)/codec_mp3_d.so
|
||||
rm -f $(DESTDIR)$(MODULES_DIR)/format_mp3.so
|
||||
rm -f $(DESTDIR)$(MODULES_DIR)/app_voicemail2.so
|
||||
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds
|
||||
mkdir -p $(DESTDIR)$(ASTLOGDIR)/cdr-csv
|
||||
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/keys
|
||||
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/firmware
|
||||
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/firmware/iax
|
||||
mkdir -p $(DESTDIR)$(ASTMANDIR)/man8
|
||||
install -m 644 keys/iaxtel.pub $(DESTDIR)$(ASTVARLIBDIR)/keys
|
||||
install -m 644 keys/freeworlddialup.pub $(DESTDIR)$(ASTVARLIBDIR)/keys
|
||||
install -m 644 asterisk.8.gz $(DESTDIR)$(ASTMANDIR)/man8
|
||||
if [ -d contrib/firmware/iax ]; then \
|
||||
install -m 644 contrib/firmware/iax/iaxy.bin $(DESTDIR)$(ASTVARLIBDIR)/firmware/iax/iaxy.bin; \
|
||||
else \
|
||||
echo "You need to do cvs update -d not just cvs update" ; \
|
||||
fi
|
||||
( cd $(DESTDIR)$(ASTVARLIBDIR)/sounds ; ln -s $(ASTSPOOLDIR)/vm . )
|
||||
( cd $(DESTDIR)$(ASTVARLIBDIR)/sounds ; ln -s $(ASTSPOOLDIR)/voicemail . )
|
||||
if [ -f mpg123-0.59r/mpg123 ]; then $(MAKE) -C mpg123-0.59r install; fi
|
||||
@echo " +---- Asterisk Installation Complete -------+"
|
||||
@echo " + +"
|
||||
@echo " + YOU MUST READ THE SECURITY DOCUMENT +"
|
||||
@@ -470,13 +392,12 @@ samples: all datafiles adsi
|
||||
for x in sounds/*.mp3; do \
|
||||
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/mohmp3 ; \
|
||||
done
|
||||
rm -f $(DESTDIR)$(ASTVARLIBDIR)/mohmp3/sample-hold.mp3
|
||||
mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/INBOX
|
||||
:> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/unavail.gsm
|
||||
for x in vm-theperson digits/1 digits/2 digits/3 digits/4 vm-isunavail; do \
|
||||
cat $(DESTDIR)$(ASTVARLIBDIR)/sounds/$$x.gsm >> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/unavail.gsm ; \
|
||||
done
|
||||
:> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/busy.gsm
|
||||
:> $(DESTDIR)$(ASTVARLIBDIR)/sounds/voicemail/default/1234/busy.gsm
|
||||
for x in vm-theperson digits/1 digits/2 digits/3 digits/4 vm-isonphone; do \
|
||||
cat $(DESTDIR)$(ASTVARLIBDIR)/sounds/$$x.gsm >> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/busy.gsm ; \
|
||||
done
|
||||
@@ -501,6 +422,7 @@ webvmail:
|
||||
|
||||
mailbox:
|
||||
./contrib/scripts/addmailbox
|
||||
|
||||
|
||||
rpm: __rpm
|
||||
|
||||
@@ -513,16 +435,10 @@ __rpm: _version
|
||||
cp -f redhat/asterisk /tmp/asterisk/etc/rc.d/init.d/ ; \
|
||||
sed "s/^Version:.*/Version: $(RPMVERSION)/g" redhat/asterisk.spec > asterisk.spec ; \
|
||||
rpmbuild --rcfile /usr/lib/rpm/rpmrc:redhat/rpmrc -bb asterisk.spec
|
||||
|
||||
|
||||
progdocs:
|
||||
doxygen contrib/asterisk-ng-doxygen
|
||||
|
||||
mpg123:
|
||||
@wget -V >/dev/null || (echo "You need wget" ; false )
|
||||
[ -f mpg123-0.59r.tar.gz ] || wget http://www.mpg123.de/mpg123/mpg123-0.59r.tar.gz
|
||||
[ -d mpg123-0.59r ] || tar xfz mpg123-0.59r.tar.gz
|
||||
$(MAKE) -C mpg123-0.59r $(MPG123TARG)
|
||||
|
||||
config:
|
||||
if [ -d /etc/rc.d/init.d ]; then \
|
||||
install -m 755 contrib/init.d/rc.redhat.asterisk /etc/rc.d/init.d/asterisk; \
|
||||
@@ -531,6 +447,7 @@ config:
|
||||
install -m 755 init.asterisk /etc/init.d/asterisk; \
|
||||
fi
|
||||
|
||||
|
||||
dont-optimize:
|
||||
$(MAKE) OPTIMIZE= K6OPT= install
|
||||
|
||||
@@ -540,21 +457,6 @@ depend: .depend
|
||||
for x in $(SUBDIRS); do $(MAKE) -C $$x depend || exit 1 ; done
|
||||
|
||||
.depend:
|
||||
@if ! which mpg123 &>/dev/null ; then \
|
||||
echo "*** You don't have mpg123 installed. You're going to need ***";\
|
||||
echo "*** it if you want MusicOnHold ***";\
|
||||
elif ! mpg123 --longhelp 2>&1 | grep .59r &>/dev/null ; then \
|
||||
echo "*************************************************************";\
|
||||
echo "*** You have the WRONG version of mpg123... you need .59r ***";\
|
||||
echo "*** Use 'make mpg123' to get the right verison ***";\
|
||||
echo "*************************************************************";\
|
||||
fi
|
||||
./mkdep ${CFLAGS} `ls *.c`
|
||||
|
||||
FORCE:
|
||||
|
||||
%_env:
|
||||
$(MAKE) -C $(shell echo $@ | sed "s/_env//g") env
|
||||
|
||||
env:
|
||||
env
|
||||
|
||||
23
README
23
README
@@ -14,17 +14,12 @@ on the project itself, please visit the Asterisk home page at:
|
||||
|
||||
http://www.asterisk.org
|
||||
|
||||
In addition you'll find lot's of information compiled by the Asterisk
|
||||
community on this Wiki:
|
||||
|
||||
http://www.voip-info.org/wiki-Asterisk
|
||||
|
||||
* LICENSING
|
||||
Asterisk is distributed under GNU General Public License. The GPL also
|
||||
must apply to all loadable modules as well, except as defined below.
|
||||
|
||||
Digium, Inc. (formerly Linux Support Services) retains copyright to all
|
||||
of the core Asterisk system, and therefore can grant, at its sole discretion,
|
||||
of the core Asterisk system, and therefore can grant, at its sole discression,
|
||||
the ability for companies, individuals, or organizations to create proprietary
|
||||
or Open Source (but non-GPL'd) modules which may be dynamically linked at
|
||||
runtime with the portions of Asterisk which fall under our copyright
|
||||
@@ -34,7 +29,7 @@ umbrella, or are distributed under more flexible licenses than GPL.
|
||||
If you wish to use our code in other GPL programs, don't worry -- there
|
||||
is no requirement that you provide the same exemption in your GPL'd
|
||||
products (although if you've written a module for Asterisk we would
|
||||
strongly encourage you to make the same exemption that we do).
|
||||
strongly encourage you to make the same excemption that we do).
|
||||
|
||||
Specific permission is also granted to OpenSSL and OpenH323 to link to
|
||||
Asterisk.
|
||||
@@ -50,12 +45,13 @@ licensing scheme are added to the Asterisk-addons CVS module.
|
||||
== Linux ==
|
||||
Currently, the Asterisk Open Source PBX is only known to run on the
|
||||
Linux OS, although it may be portable to other UNIX-like operating systems
|
||||
(like FreeBSD) as well.
|
||||
as well.
|
||||
|
||||
|
||||
* GETTING STARTED
|
||||
|
||||
First, be sure you've got supported hardware (but note that you don't need ANY hardware, not even a soundcard) to install and run Asterisk. Supported are:
|
||||
First, be sure you've got supported hardware. To use Asterisk right now,
|
||||
you will need one of the following:
|
||||
|
||||
* All Wildcard (tm) products from Digium (www.digium.com)
|
||||
* QuickNet Internet PhoneJack and LineJack (http://www.quicknet.net)
|
||||
@@ -64,9 +60,8 @@ First, be sure you've got supported hardware (but note that you don't need ANY h
|
||||
* ISDN4Linux compatible ISDN card
|
||||
* Tormenta Dual T1 card (www.bsdtelephony.com.mx)
|
||||
|
||||
Hint: CAPI compatible ISDN cards can be run using the add-on channel chan_capi.
|
||||
|
||||
So let's proceed:
|
||||
Assuming you have one of these (most likely the third) you're ready to
|
||||
proceed:
|
||||
|
||||
1) Run "make"
|
||||
2) Run "make install"
|
||||
@@ -76,7 +71,7 @@ the sample PBX, with demonstration extensions, etc. If so, run:
|
||||
|
||||
"make samples"
|
||||
|
||||
Doing so will overwrite any existing config files you have. If you are lacking a soundcard you won't be able to use the DIAL command on the console, though.
|
||||
Doing so will overwrite any existing config files you have.
|
||||
|
||||
Finally, you can launch Asterisk with:
|
||||
|
||||
@@ -148,5 +143,3 @@ you're interested in getting more information.
|
||||
Welcome to the growing worldwide community of Asterisk users!
|
||||
|
||||
Mark Spencer
|
||||
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
About Hold Music
|
||||
================
|
||||
These files were obtained from http://opsound.org, where the authors placed them
|
||||
under the Creative Commons Attribution-Share Alike 2.5 license, a copy of which
|
||||
may be found at http://creativecommons.org.
|
||||
|
||||
Credits
|
||||
================
|
||||
macroform-cold_day - Paul Shuler (Macroform)
|
||||
paulshuler@gmail.com - http://macroform.bandcamp.com/
|
||||
|
||||
macroform-robot_dity - Paul Shuler (Macroform)
|
||||
paulshuler@gmail.com - http://macroform.bandcamp.com/
|
||||
|
||||
macroform-the_simplicity - Paul Shuler (Macroform)
|
||||
paulshuler@gmail.com - http://macroform.bandcamp.com/
|
||||
|
||||
manolo_camp-morning_coffee - Manolo Camp
|
||||
beatbastard@gmx.net - http://ccmixter.org/people/ManoloCamp
|
||||
|
||||
reno_project-system - Reno Project
|
||||
renoproject@hotmail.com - http://www.jamendo.com/en/album/23661
|
||||
6
SECURITY
6
SECURITY
@@ -25,15 +25,15 @@ the "default" context within other private contexts by using:
|
||||
in the appropriate section. A well designed PBX might look like this:
|
||||
|
||||
[longdistance]
|
||||
exten => _91NXXNXXXXXX,1,Dial(Zap/g2/${EXTEN:1})
|
||||
exten => _91NXXNXXXXXX,1,Dial,Tor/g2/BYEXTENSION
|
||||
include => local
|
||||
|
||||
[local]
|
||||
exten => _9NXXNXXX,1,Dial(Zap/g2/${EXTEN:1})
|
||||
exten => _9NXXNXXX,1,Dial,Tor/g2/BYEXTENSION
|
||||
include => default
|
||||
|
||||
[default]
|
||||
exten => 6123,Dial(Zap/1)
|
||||
exten => 6123,Dial,Tor/1
|
||||
|
||||
|
||||
DON'T FORGET TO TAKE THE DEMO CONTEXT OUT OF YOUR DEFAULT CONTEXT. There
|
||||
|
||||
138
acl.c
138
acl.c
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
@@ -21,8 +22,6 @@
|
||||
#include <asterisk/acl.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
@@ -30,13 +29,15 @@
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/ioctl.h>
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
|
||||
#ifdef __OpenBSD__
|
||||
#include <fcntl.h>
|
||||
#include <net/route.h>
|
||||
|
||||
AST_MUTEX_DEFINE_STATIC(routeseq_lock);
|
||||
static ast_mutex_t routeseq_lock = AST_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
|
||||
#define AST_SENSE_DENY 0
|
||||
#define AST_SENSE_ALLOW 1
|
||||
|
||||
struct ast_ha {
|
||||
/* Host access rule */
|
||||
@@ -54,7 +55,6 @@ struct my_ifreq {
|
||||
struct sockaddr_in ifru_addr;
|
||||
};
|
||||
|
||||
/* Free HA structure */
|
||||
void ast_free_ha(struct ast_ha *ha)
|
||||
{
|
||||
struct ast_ha *hal;
|
||||
@@ -65,52 +65,10 @@ void ast_free_ha(struct ast_ha *ha)
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy HA structure */
|
||||
static void ast_copy_ha(struct ast_ha *from, struct ast_ha *to)
|
||||
{
|
||||
memcpy(&to->netaddr, &from->netaddr, sizeof(from->netaddr));
|
||||
memcpy(&to->netmask, &from->netmask, sizeof(from->netmask));
|
||||
to->sense = from->sense;
|
||||
}
|
||||
|
||||
/* Create duplicate of ha structure */
|
||||
static struct ast_ha *ast_duplicate_ha(struct ast_ha *original)
|
||||
{
|
||||
struct ast_ha *new_ha = malloc(sizeof(struct ast_ha));
|
||||
|
||||
/* Copy from original to new object */
|
||||
ast_copy_ha(original, new_ha);
|
||||
|
||||
return(new_ha);
|
||||
|
||||
}
|
||||
|
||||
/* Create duplicate HA link list */
|
||||
/* Used in chan_sip2 templates */
|
||||
struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original)
|
||||
{
|
||||
struct ast_ha *start=original;
|
||||
struct ast_ha *ret = NULL;
|
||||
struct ast_ha *link,*prev=NULL;
|
||||
|
||||
while(start) {
|
||||
link = ast_duplicate_ha(start); /* Create copy of this object */
|
||||
if (prev)
|
||||
prev->next = link; /* Link previous to this object */
|
||||
|
||||
if (!ret)
|
||||
ret = link; /* Save starting point */
|
||||
|
||||
start = start->next; /* Go to next object */
|
||||
prev = link; /* Save pointer to this object */
|
||||
}
|
||||
return (ret); /* Return start of list */
|
||||
}
|
||||
|
||||
struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
|
||||
{
|
||||
struct ast_ha *ha = malloc(sizeof(struct ast_ha));
|
||||
char *nm="255.255.255.255";
|
||||
char *nm;
|
||||
char tmp[256] = "";
|
||||
struct ast_ha *prev = NULL;
|
||||
struct ast_ha *ret;
|
||||
@@ -161,7 +119,6 @@ struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
|
||||
else
|
||||
ret = ha;
|
||||
}
|
||||
ast_log(LOG_DEBUG, "%s/%s appended to acl for peer\n",stuff, nm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -170,13 +127,6 @@ int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
|
||||
/* Start optimistic */
|
||||
int res = AST_SENSE_ALLOW;
|
||||
while(ha) {
|
||||
char iabuf[INET_ADDRSTRLEN];
|
||||
char iabuf2[INET_ADDRSTRLEN];
|
||||
/* DEBUG */
|
||||
ast_log(LOG_DEBUG,
|
||||
"##### Testing %s with %s\n",
|
||||
ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr),
|
||||
ast_inet_ntoa(iabuf2, sizeof(iabuf2), ha->netaddr));
|
||||
/* For each rule, if this address and the netmask = the net address
|
||||
apply the current rule */
|
||||
if ((sin->sin_addr.s_addr & ha->netmask.s_addr) == (ha->netaddr.s_addr))
|
||||
@@ -189,8 +139,7 @@ int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
|
||||
int ast_get_ip(struct sockaddr_in *sin, char *value)
|
||||
{
|
||||
struct hostent *hp;
|
||||
struct ast_hostent ahp;
|
||||
hp = ast_gethostbyname(value, &ahp);
|
||||
hp = gethostbyname(value);
|
||||
if (hp) {
|
||||
memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
|
||||
} else {
|
||||
@@ -200,6 +149,12 @@ int ast_get_ip(struct sockaddr_in *sin, char *value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int inaddrcmp(struct sockaddr_in *sin1, struct sockaddr_in *sin2)
|
||||
{
|
||||
return ((sin1->sin_addr.s_addr != sin2->sin_addr.s_addr )
|
||||
|| (sin1->sin_port != sin2->sin_port));
|
||||
}
|
||||
|
||||
/* iface is the interface (e.g. eth0); address is the return value */
|
||||
int ast_lookup_iface(char *iface, struct in_addr *address) {
|
||||
int mysock, res = 0;
|
||||
@@ -224,37 +179,36 @@ int ast_lookup_iface(char *iface, struct in_addr *address) {
|
||||
|
||||
int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
|
||||
{
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
|
||||
#ifdef __OpenBSD__
|
||||
struct sockaddr_in *sin;
|
||||
struct sockaddr *sa;
|
||||
struct {
|
||||
struct rt_msghdr m_rtm;
|
||||
char m_space[512];
|
||||
} m_rtmsg;
|
||||
char iabuf[INET_ADDRSTRLEN];
|
||||
char *cp, *p;
|
||||
char *cp, *p = ast_strdupa(inet_ntoa(*them));
|
||||
int i, l, s, seq, flags;
|
||||
pid_t pid = getpid();
|
||||
static int routeseq; /* Protected by "routeseq_lock" mutex */
|
||||
|
||||
p = ast_strdupa(ast_inet_ntoa(iabuf, sizeof(iabuf), *them));
|
||||
memset(us, 0, sizeof(struct in_addr));
|
||||
|
||||
memset(&m_rtmsg, 0, sizeof(m_rtmsg));
|
||||
m_rtmsg.m_rtm.rtm_type = RTM_GET;
|
||||
m_rtmsg.m_rtm.rtm_flags = RTF_UP | RTF_HOST;
|
||||
m_rtmsg.m_rtm.rtm_version = RTM_VERSION;
|
||||
ast_mutex_lock(&routeseq_lock);
|
||||
seq = ++routeseq;
|
||||
ast_mutex_unlock(&routeseq_lock);
|
||||
m_rtmsg.m_rtm.rtm_seq = seq;
|
||||
m_rtmsg.m_rtm.rtm_addrs = RTA_DST | RTA_IFA;
|
||||
m_rtmsg.m_rtm.rtm_addrs = RTA_IFA | RTA_DST;
|
||||
m_rtmsg.m_rtm.rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in);
|
||||
sin = (struct sockaddr_in *)m_rtmsg.m_space;
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_len = sizeof(struct sockaddr_in);
|
||||
sin->sin_addr = *them;
|
||||
|
||||
if ((s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC)) < 0) {
|
||||
if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
|
||||
ast_log(LOG_ERROR, "Error opening routing socket\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -267,7 +221,7 @@ int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
|
||||
}
|
||||
do {
|
||||
l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
|
||||
} while (l > 0 && (m_rtmsg.m_rtm.rtm_seq != seq || m_rtmsg.m_rtm.rtm_pid != pid));
|
||||
} while (l > 0 && (m_rtmsg.m_rtm.rtm_seq != 1 || m_rtmsg.m_rtm.rtm_pid != pid));
|
||||
if (l < 0) {
|
||||
if (errno != EAGAIN)
|
||||
ast_log(LOG_ERROR, "Error reading from routing socket\n");
|
||||
@@ -299,7 +253,7 @@ int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
|
||||
if (i == RTA_IFA && sa->sa_family == AF_INET) {
|
||||
sin = (struct sockaddr_in *)sa;
|
||||
*us = sin->sin_addr;
|
||||
ast_log(LOG_DEBUG, "Found route to %s, output from our address %s.\n", p, ast_inet_ntoa(iabuf, sizeof(iabuf), *us));
|
||||
ast_log(LOG_DEBUG, "Found route to %s, output from our address %s.\n", p, inet_ntoa(*us));
|
||||
return 0;
|
||||
}
|
||||
cp += sa->sa_len > 0 ?
|
||||
@@ -325,7 +279,7 @@ int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
|
||||
fgets(line,sizeof(line),PROC);
|
||||
|
||||
while (!feof(PROC)) {
|
||||
char iface[256];
|
||||
char iface[8];
|
||||
unsigned int dest, gateway, mask;
|
||||
int i,fieldnum;
|
||||
char *fields[40];
|
||||
@@ -349,21 +303,18 @@ int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
|
||||
i = offset - line;
|
||||
}
|
||||
}
|
||||
if (fieldnum >= 8) {
|
||||
|
||||
sscanf(fields[0],"%s",iface);
|
||||
sscanf(fields[1],"%x",&dest);
|
||||
sscanf(fields[2],"%x",&gateway);
|
||||
sscanf(fields[7],"%x",&mask);
|
||||
sscanf(fields[0],"%s",iface);
|
||||
sscanf(fields[1],"%x",&dest);
|
||||
sscanf(fields[2],"%x",&gateway);
|
||||
sscanf(fields[7],"%x",&mask);
|
||||
#if 0
|
||||
{ char iabuf[INET_ADDRSTRLEN];
|
||||
printf("Addr: %s %08x Dest: %08x Mask: %08x\n", ast_inet_ntoa(iabuf, sizeof(iabuf), *them), remote_ip, dest, mask); }
|
||||
printf("Addr: %s %08x Dest: %08x Mask: %08x\n", inet_ntoa(*them), remote_ip, dest, mask);
|
||||
#endif
|
||||
/* Looks simple, but here is the magic */
|
||||
if (((remote_ip & mask) ^ dest) == 0) {
|
||||
res = ast_lookup_iface(iface,us);
|
||||
break;
|
||||
}
|
||||
/* Looks simple, but here is the magic */
|
||||
if (((remote_ip & mask) ^ dest) == 0) {
|
||||
res = ast_lookup_iface(iface,us);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(PROC);
|
||||
@@ -378,32 +329,3 @@ int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ast_find_ourip(struct in_addr *ourip, struct sockaddr_in bindaddr)
|
||||
{
|
||||
char ourhost[256];
|
||||
struct ast_hostent ahp;
|
||||
struct hostent *hp;
|
||||
struct in_addr saddr;
|
||||
|
||||
/* just use the bind address if it is nonzero */
|
||||
if (ntohl(bindaddr.sin_addr.s_addr)) {
|
||||
memcpy(ourip, &bindaddr.sin_addr, sizeof(*ourip));
|
||||
return 0;
|
||||
}
|
||||
/* try to use our hostname */
|
||||
if (gethostname(ourhost, sizeof(ourhost))) {
|
||||
ast_log(LOG_WARNING, "Unable to get hostname\n");
|
||||
} else {
|
||||
hp = ast_gethostbyname(ourhost, &ahp);
|
||||
if (hp) {
|
||||
memcpy(ourip, hp->h_addr, sizeof(*ourip));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* A.ROOT-SERVERS.NET. */
|
||||
if (inet_aton("198.41.0.4", &saddr) && !ast_ouraddrfor(&saddr, ourip))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
10
aesopt.h
10
aesopt.h
@@ -148,19 +148,13 @@
|
||||
|
||||
/* PLATFORM SPECIFIC INCLUDES */
|
||||
|
||||
#if defined( __OpenBSD__ )
|
||||
# include <machine/types.h>
|
||||
#if defined( __FreeBSD__ ) || defined( __OpenBSD__ )
|
||||
# include <sys/endian.h>
|
||||
#elif defined( __FreeBSD__ ) || defined( __NetBSD__ )
|
||||
# include <sys/types.h>
|
||||
# include <sys/endian.h>
|
||||
#elif defined( BSD ) && ( BSD >= 199103 ) || defined(__APPLE__)
|
||||
#elif defined( BSD ) && ( BSD >= 199103 )
|
||||
# include <machine/endian.h>
|
||||
#elif defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
|
||||
# include <endian.h>
|
||||
#if !defined(__APPLE__)
|
||||
# include <byteswap.h>
|
||||
#endif
|
||||
#elif defined( linux )
|
||||
# include <endian.h>
|
||||
#endif
|
||||
|
||||
@@ -22,13 +22,13 @@ install: all
|
||||
for x in $(AGIS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(AGI_DIR) ; done
|
||||
|
||||
eagi-test: eagi-test.o
|
||||
$(CC) $(CFLAGS) -o eagi-test eagi-test.o
|
||||
|
||||
$(CC) -o eagi-test eagi-test.o
|
||||
|
||||
eagi-sphinx-test: eagi-sphinx-test.o
|
||||
$(CC) $(CFLAGS) -o eagi-sphinx-test eagi-sphinx-test.o
|
||||
$(CC) -o eagi-sphinx-test eagi-sphinx-test.o
|
||||
|
||||
clean:
|
||||
rm -f *.so *.o look .depend eagi-test eagi-sphinx-test
|
||||
rm -f *.so *.o look .depend
|
||||
|
||||
%.so : %.o
|
||||
$(CC) -shared -Xlinker -x -o $@ $<
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
#!/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(<CLIENT>) {
|
||||
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 = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "2. Testing 'sendtext'...";
|
||||
print CLIENT "SEND TEXT \"hello world\"\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "3. Testing 'sendimage'...";
|
||||
print CLIENT "SEND IMAGE asterisk-image\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "4. Testing 'saynumber'...";
|
||||
print CLIENT "SAY NUMBER 192837465 \"\"\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "5. Testing 'waitdtmf'...";
|
||||
print CLIENT "WAIT FOR DIGIT 1000\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "6. Testing 'record'...";
|
||||
print CLIENT "RECORD FILE testagi gsm 1234 3000\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "6a. Testing 'record' playback...";
|
||||
print CLIENT "STREAM FILE testagi \"\"\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
close(CLIENT);
|
||||
print STDERR "================== Complete ======================\n";
|
||||
print STDERR "$tests tests completed, $pass passed, $fail failed\n";
|
||||
print STDERR "==================================================\n";
|
||||
}
|
||||
|
||||
771
app.c
771
app.c
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Convenient Application Routines
|
||||
* Channel Management
|
||||
*
|
||||
* Copyright (C) 1999-2004, Digium, Inc.
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
@@ -26,21 +27,15 @@
|
||||
#include <asterisk/dsp.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include "asterisk.h"
|
||||
#include "astconf.h"
|
||||
|
||||
#define MAX_OTHER_FORMATS 10
|
||||
|
||||
/* set timeout to 0 for "standard" timeouts. Set timeout to -1 for
|
||||
"ludicrous time" (essentially never times out) */
|
||||
int ast_app_getdata(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout)
|
||||
{
|
||||
int res,to,fto;
|
||||
/* XXX Merge with full version? XXX */
|
||||
if (maxlen)
|
||||
s[0] = '\0';
|
||||
if (prompt) {
|
||||
res = ast_streamfile(c, prompt, c->language);
|
||||
if (res < 0)
|
||||
@@ -158,14 +153,14 @@ int ast_app_has_voicemail(const char *mailbox)
|
||||
char *context;
|
||||
int ret;
|
||||
/* If no mailbox, return immediately */
|
||||
if (ast_strlen_zero(mailbox))
|
||||
if (!strlen(mailbox))
|
||||
return 0;
|
||||
if (strchr(mailbox, ',')) {
|
||||
strncpy(tmp, mailbox, sizeof(tmp) - 1);
|
||||
strncpy(tmp, mailbox, sizeof(tmp));
|
||||
mb = tmp;
|
||||
ret = 0;
|
||||
while((cur = strsep(&mb, ","))) {
|
||||
if (!ast_strlen_zero(cur)) {
|
||||
if (strlen(cur)) {
|
||||
if (ast_app_has_voicemail(cur))
|
||||
return 1;
|
||||
}
|
||||
@@ -207,15 +202,15 @@ int ast_app_messagecount(const char *mailbox, int *newmsgs, int *oldmsgs)
|
||||
if (oldmsgs)
|
||||
*oldmsgs = 0;
|
||||
/* If no mailbox, return immediately */
|
||||
if (ast_strlen_zero(mailbox))
|
||||
if (!strlen(mailbox))
|
||||
return 0;
|
||||
if (strchr(mailbox, ',')) {
|
||||
int tmpnew, tmpold;
|
||||
strncpy(tmp, mailbox, sizeof(tmp) - 1);
|
||||
strncpy(tmp, mailbox, sizeof(tmp));
|
||||
mb = tmp;
|
||||
ret = 0;
|
||||
while((cur = strsep(&mb, ", "))) {
|
||||
if (!ast_strlen_zero(cur)) {
|
||||
if (strlen(cur)) {
|
||||
if (ast_app_messagecount(cur, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
|
||||
return -1;
|
||||
else {
|
||||
@@ -263,749 +258,3 @@ int ast_app_messagecount(const char *mailbox, int *newmsgs, int *oldmsgs)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ast_dtmf_stream(struct ast_channel *chan,struct ast_channel *peer,char *digits,int between)
|
||||
{
|
||||
char *ptr=NULL;
|
||||
int res=0;
|
||||
struct ast_frame f;
|
||||
if (!between)
|
||||
between = 100;
|
||||
|
||||
if (peer)
|
||||
res = ast_autoservice_start(peer);
|
||||
|
||||
if (!res) {
|
||||
res = ast_waitfor(chan,100);
|
||||
if (res > -1) {
|
||||
for (ptr=digits;*ptr;*ptr++) {
|
||||
if (*ptr == 'w') {
|
||||
res = ast_safe_sleep(chan, 500);
|
||||
if (res)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
memset(&f, 0, sizeof(f));
|
||||
f.frametype = AST_FRAME_DTMF;
|
||||
f.subclass = *ptr;
|
||||
f.src = "ast_dtmf_stream";
|
||||
if (strchr("0123456789*#abcdABCD",*ptr)==NULL) {
|
||||
ast_log(LOG_WARNING, "Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n",*ptr);
|
||||
} else {
|
||||
res = ast_write(chan, &f);
|
||||
if (res)
|
||||
break;
|
||||
/* pause between digits */
|
||||
res = ast_safe_sleep(chan,between);
|
||||
if (res)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (peer)
|
||||
res = ast_autoservice_stop(peer);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
struct linear_state {
|
||||
int fd;
|
||||
int autoclose;
|
||||
int allowoverride;
|
||||
int origwfmt;
|
||||
};
|
||||
|
||||
static void linear_release(struct ast_channel *chan, void *params)
|
||||
{
|
||||
struct linear_state *ls = params;
|
||||
if (ls->origwfmt && ast_set_write_format(chan, ls->origwfmt)) {
|
||||
ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%d'\n", chan->name, ls->origwfmt);
|
||||
}
|
||||
if (ls->autoclose)
|
||||
close(ls->fd);
|
||||
free(params);
|
||||
}
|
||||
|
||||
static int linear_generator(struct ast_channel *chan, void *data, int len, int samples)
|
||||
{
|
||||
struct ast_frame f;
|
||||
short buf[2048 + AST_FRIENDLY_OFFSET / 2];
|
||||
struct linear_state *ls = data;
|
||||
int res;
|
||||
len = samples * 2;
|
||||
if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
|
||||
ast_log(LOG_WARNING, "Can't generate %d bytes of data!\n" ,len);
|
||||
len = sizeof(buf) - AST_FRIENDLY_OFFSET;
|
||||
}
|
||||
memset(&f, 0, sizeof(f));
|
||||
res = read(ls->fd, buf + AST_FRIENDLY_OFFSET/2, len);
|
||||
if (res > 0) {
|
||||
f.frametype = AST_FRAME_VOICE;
|
||||
f.subclass = AST_FORMAT_SLINEAR;
|
||||
f.data = buf + AST_FRIENDLY_OFFSET/2;
|
||||
f.datalen = res;
|
||||
f.samples = res / 2;
|
||||
f.offset = AST_FRIENDLY_OFFSET;
|
||||
ast_write(chan, &f);
|
||||
if (res == len)
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void *linear_alloc(struct ast_channel *chan, void *params)
|
||||
{
|
||||
struct linear_state *ls;
|
||||
/* In this case, params is already malloc'd */
|
||||
if (params) {
|
||||
ls = params;
|
||||
if (ls->allowoverride)
|
||||
chan->writeinterrupt = 1;
|
||||
else
|
||||
chan->writeinterrupt = 0;
|
||||
ls->origwfmt = chan->writeformat;
|
||||
if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
|
||||
ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", chan->name);
|
||||
free(ls);
|
||||
ls = params = NULL;
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
static struct ast_generator linearstream =
|
||||
{
|
||||
alloc: linear_alloc,
|
||||
release: linear_release,
|
||||
generate: linear_generator,
|
||||
};
|
||||
|
||||
int ast_linear_stream(struct ast_channel *chan, const char *filename, int fd, int allowoverride)
|
||||
{
|
||||
struct linear_state *lin;
|
||||
char tmpf[256] = "";
|
||||
int res = -1;
|
||||
int autoclose = 0;
|
||||
if (fd < 0) {
|
||||
if (!filename || ast_strlen_zero(filename))
|
||||
return -1;
|
||||
autoclose = 1;
|
||||
if (filename[0] == '/')
|
||||
strncpy(tmpf, filename, sizeof(tmpf) - 1);
|
||||
else
|
||||
snprintf(tmpf, sizeof(tmpf), "%s/%s/%s", (char *)ast_config_AST_VAR_DIR, "sounds", filename);
|
||||
fd = open(tmpf, O_RDONLY);
|
||||
if (fd < 0){
|
||||
ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", tmpf, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
lin = malloc(sizeof(struct linear_state));
|
||||
if (lin) {
|
||||
memset(lin, 0, sizeof(lin));
|
||||
lin->fd = fd;
|
||||
lin->allowoverride = allowoverride;
|
||||
lin->autoclose = autoclose;
|
||||
res = ast_activate_generator(chan, &linearstream, lin);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int ast_control_streamfile(struct ast_channel *chan, char *file, char *fwd, char *rev, char *stop, char *pause, int skipms)
|
||||
{
|
||||
struct timeval started, ended;
|
||||
long elapsed = 0,last_elapsed =0;
|
||||
char *breaks=NULL;
|
||||
char *end=NULL;
|
||||
int blen=2;
|
||||
int res=0;
|
||||
|
||||
if (stop)
|
||||
blen += strlen(stop);
|
||||
if (pause)
|
||||
blen += strlen(pause);
|
||||
|
||||
if (blen > 2) {
|
||||
breaks = alloca(blen + 1);
|
||||
breaks[0] = '\0';
|
||||
strcat(breaks, stop);
|
||||
strcat(breaks, pause);
|
||||
}
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
res = ast_answer(chan);
|
||||
|
||||
if (chan)
|
||||
ast_stopstream(chan);
|
||||
|
||||
|
||||
if (file) {
|
||||
if ((end = strchr(file,':'))) {
|
||||
if (!strcasecmp(end, ":end")) {
|
||||
*end = '\0';
|
||||
end++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
gettimeofday(&started,NULL);
|
||||
|
||||
if (chan)
|
||||
ast_stopstream(chan);
|
||||
res = ast_streamfile(chan, file, chan->language);
|
||||
if (!res) {
|
||||
if (end) {
|
||||
ast_seekstream(chan->stream, 0, SEEK_END);
|
||||
end=NULL;
|
||||
}
|
||||
res = 1;
|
||||
if (elapsed) {
|
||||
ast_stream_fastforward(chan->stream, elapsed);
|
||||
last_elapsed = elapsed - 200;
|
||||
}
|
||||
if (res)
|
||||
res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (res < 1)
|
||||
break;
|
||||
|
||||
if (pause != NULL && strchr(pause, res)) {
|
||||
gettimeofday(&ended, NULL);
|
||||
elapsed = (((ended.tv_sec * 1000) + ended.tv_usec / 1000) - ((started.tv_sec * 1000) + started.tv_usec / 1000) + last_elapsed);
|
||||
for(;;) {
|
||||
if (chan)
|
||||
ast_stopstream(chan);
|
||||
res = ast_waitfordigit(chan, 1000);
|
||||
if (res == 0)
|
||||
continue;
|
||||
else if (res == -1 || strchr(pause, res) || (stop && strchr(stop, res)))
|
||||
break;
|
||||
}
|
||||
if (res == *pause) {
|
||||
res = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (res == -1)
|
||||
break;
|
||||
|
||||
/* if we get one of our stop chars, return it to the calling function */
|
||||
if (stop && strchr(stop, res)) {
|
||||
/* res = 0; */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (chan)
|
||||
ast_stopstream(chan);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int ast_play_and_wait(struct ast_channel *chan, char *fn)
|
||||
{
|
||||
int d;
|
||||
d = ast_streamfile(chan, fn, chan->language);
|
||||
if (d)
|
||||
return d;
|
||||
d = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
ast_stopstream(chan);
|
||||
return d;
|
||||
}
|
||||
|
||||
static int global_silence_threshold = 128;
|
||||
static int global_maxsilence = 0;
|
||||
|
||||
int ast_play_and_record(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int silencethreshold, int maxsilence, const char *path)
|
||||
{
|
||||
char d, *fmts;
|
||||
char comment[256];
|
||||
int x, fmtcnt=1, res=-1,outmsg=0;
|
||||
struct ast_frame *f;
|
||||
struct ast_filestream *others[MAX_OTHER_FORMATS];
|
||||
char *sfmt[MAX_OTHER_FORMATS];
|
||||
char *stringp=NULL;
|
||||
time_t start, end;
|
||||
struct ast_dsp *sildet=NULL; /* silence detector dsp */
|
||||
int totalsilence = 0;
|
||||
int dspsilence = 0;
|
||||
int gotsilence = 0; /* did we timeout for silence? */
|
||||
int rfmt=0;
|
||||
|
||||
if (silencethreshold < 0)
|
||||
silencethreshold = global_silence_threshold;
|
||||
|
||||
if (maxsilence < 0)
|
||||
maxsilence = global_maxsilence;
|
||||
|
||||
/* barf if no pointer passed to store duration in */
|
||||
if (duration == NULL) {
|
||||
ast_log(LOG_WARNING, "Error play_and_record called without duration pointer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ast_log(LOG_DEBUG,"play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
|
||||
snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name);
|
||||
|
||||
if (playfile) {
|
||||
d = ast_play_and_wait(chan, playfile);
|
||||
if (d > -1)
|
||||
d = ast_streamfile(chan, "beep",chan->language);
|
||||
if (!d)
|
||||
d = ast_waitstream(chan,"");
|
||||
if (d < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
fmts = ast_strdupa(fmt);
|
||||
|
||||
stringp=fmts;
|
||||
strsep(&stringp, "|");
|
||||
ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts);
|
||||
sfmt[0] = ast_strdupa(fmts);
|
||||
|
||||
while((fmt = strsep(&stringp, "|"))) {
|
||||
if (fmtcnt > MAX_OTHER_FORMATS - 1) {
|
||||
ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n");
|
||||
break;
|
||||
}
|
||||
sfmt[fmtcnt++] = ast_strdupa(fmt);
|
||||
}
|
||||
|
||||
time(&start);
|
||||
end=start; /* pre-initialize end to be same as start in case we never get into loop */
|
||||
for (x=0;x<fmtcnt;x++) {
|
||||
others[x] = ast_writefile(recordfile, sfmt[x], comment, O_TRUNC, 0, 0700);
|
||||
ast_verbose( VERBOSE_PREFIX_3 "x=%i, open writing: %s format: %s, %p\n", x, recordfile, sfmt[x], others[x]);
|
||||
|
||||
if (!others[x]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (path)
|
||||
ast_unlock_path(path);
|
||||
|
||||
|
||||
if (maxsilence > 0) {
|
||||
sildet = ast_dsp_new(); /* Create the silence detector */
|
||||
if (!sildet) {
|
||||
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
|
||||
return -1;
|
||||
}
|
||||
ast_dsp_set_threshold(sildet, silencethreshold);
|
||||
rfmt = chan->readformat;
|
||||
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
|
||||
ast_dsp_free(sildet);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (x == fmtcnt) {
|
||||
/* Loop forever, writing the packets we read to the writer(s), until
|
||||
we read a # or get a hangup */
|
||||
f = NULL;
|
||||
for(;;) {
|
||||
res = ast_waitfor(chan, 2000);
|
||||
if (!res) {
|
||||
ast_log(LOG_DEBUG, "One waitfor failed, trying another\n");
|
||||
/* Try one more time in case of masq */
|
||||
res = ast_waitfor(chan, 2000);
|
||||
if (!res) {
|
||||
ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (res < 0) {
|
||||
f = NULL;
|
||||
break;
|
||||
}
|
||||
f = ast_read(chan);
|
||||
if (!f)
|
||||
break;
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
/* write each format */
|
||||
for (x=0;x<fmtcnt;x++) {
|
||||
res = ast_writestream(others[x], f);
|
||||
}
|
||||
|
||||
/* Silence Detection */
|
||||
if (maxsilence > 0) {
|
||||
dspsilence = 0;
|
||||
ast_dsp_silence(sildet, f, &dspsilence);
|
||||
if (dspsilence)
|
||||
totalsilence = dspsilence;
|
||||
else
|
||||
totalsilence = 0;
|
||||
|
||||
if (totalsilence > maxsilence) {
|
||||
/* Ended happily with silence */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
|
||||
ast_frfree(f);
|
||||
gotsilence = 1;
|
||||
outmsg=2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Exit on any error */
|
||||
if (res) {
|
||||
ast_log(LOG_WARNING, "Error writing frame\n");
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
} else if (f->frametype == AST_FRAME_VIDEO) {
|
||||
/* Write only once */
|
||||
ast_writestream(others[0], f);
|
||||
} else if (f->frametype == AST_FRAME_DTMF) {
|
||||
if (f->subclass == '#') {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
|
||||
res = '#';
|
||||
outmsg = 2;
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (f->subclass == '0') {
|
||||
/* Check for a '0' during message recording also, in case caller wants operator */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "User cancelled by pressing %c\n", f->subclass);
|
||||
res = '0';
|
||||
outmsg = 0;
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
if (maxtime) {
|
||||
time(&end);
|
||||
if (maxtime < (end - start)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
|
||||
outmsg = 2;
|
||||
res = 't';
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
if (end == start) time(&end);
|
||||
if (!f) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "User hung up\n");
|
||||
res = -1;
|
||||
outmsg=1;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]);
|
||||
}
|
||||
|
||||
*duration = end - start;
|
||||
|
||||
for (x=0;x<fmtcnt;x++) {
|
||||
if (!others[x])
|
||||
break;
|
||||
if (res > 0) {
|
||||
if (totalsilence)
|
||||
ast_stream_rewind(others[x], totalsilence-200);
|
||||
else
|
||||
ast_stream_rewind(others[x], 200);
|
||||
}
|
||||
ast_truncstream(others[x]);
|
||||
ast_closestream(others[x]);
|
||||
}
|
||||
if (rfmt) {
|
||||
if (ast_set_read_format(chan, rfmt)) {
|
||||
ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
|
||||
}
|
||||
}
|
||||
if (outmsg > 1) {
|
||||
/* Let them know recording is stopped */
|
||||
if(!ast_streamfile(chan, "auth-thankyou", chan->language))
|
||||
ast_waitstream(chan, "");
|
||||
}
|
||||
if (sildet)
|
||||
ast_dsp_free(sildet);
|
||||
return res;
|
||||
}
|
||||
|
||||
int ast_play_and_prepend(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int beep, int silencethreshold, int maxsilence)
|
||||
{
|
||||
char d = 0, *fmts;
|
||||
char comment[256];
|
||||
int x, fmtcnt=1, res=-1,outmsg=0;
|
||||
struct ast_frame *f;
|
||||
struct ast_filestream *others[MAX_OTHER_FORMATS];
|
||||
struct ast_filestream *realfiles[MAX_OTHER_FORMATS];
|
||||
char *sfmt[MAX_OTHER_FORMATS];
|
||||
char *stringp=NULL;
|
||||
time_t start, end;
|
||||
struct ast_dsp *sildet; /* silence detector dsp */
|
||||
int totalsilence = 0;
|
||||
int dspsilence = 0;
|
||||
int gotsilence = 0; /* did we timeout for silence? */
|
||||
int rfmt=0;
|
||||
char prependfile[80];
|
||||
|
||||
if (silencethreshold < 0)
|
||||
silencethreshold = global_silence_threshold;
|
||||
|
||||
if (maxsilence < 0)
|
||||
maxsilence = global_maxsilence;
|
||||
|
||||
/* barf if no pointer passed to store duration in */
|
||||
if (duration == NULL) {
|
||||
ast_log(LOG_WARNING, "Error play_and_prepend called without duration pointer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ast_log(LOG_DEBUG,"play_and_prepend: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
|
||||
snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name);
|
||||
|
||||
if (playfile || beep) {
|
||||
if (!beep)
|
||||
d = ast_play_and_wait(chan, playfile);
|
||||
if (d > -1)
|
||||
d = ast_streamfile(chan, "beep",chan->language);
|
||||
if (!d)
|
||||
d = ast_waitstream(chan,"");
|
||||
if (d < 0)
|
||||
return -1;
|
||||
}
|
||||
strncpy(prependfile, recordfile, sizeof(prependfile) -1);
|
||||
strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1);
|
||||
|
||||
fmts = ast_strdupa(fmt);
|
||||
|
||||
stringp=fmts;
|
||||
strsep(&stringp, "|");
|
||||
ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts);
|
||||
sfmt[0] = ast_strdupa(fmts);
|
||||
|
||||
while((fmt = strsep(&stringp, "|"))) {
|
||||
if (fmtcnt > MAX_OTHER_FORMATS - 1) {
|
||||
ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n");
|
||||
break;
|
||||
}
|
||||
sfmt[fmtcnt++] = ast_strdupa(fmt);
|
||||
}
|
||||
|
||||
time(&start);
|
||||
end=start; /* pre-initialize end to be same as start in case we never get into loop */
|
||||
for (x=0;x<fmtcnt;x++) {
|
||||
others[x] = ast_writefile(prependfile, sfmt[x], comment, O_TRUNC, 0, 0700);
|
||||
ast_verbose( VERBOSE_PREFIX_3 "x=%i, open writing: %s format: %s, %p\n", x, prependfile, sfmt[x], others[x]);
|
||||
if (!others[x]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sildet = ast_dsp_new(); /* Create the silence detector */
|
||||
if (!sildet) {
|
||||
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
|
||||
return -1;
|
||||
}
|
||||
ast_dsp_set_threshold(sildet, silencethreshold);
|
||||
|
||||
if (maxsilence > 0) {
|
||||
rfmt = chan->readformat;
|
||||
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (x == fmtcnt) {
|
||||
/* Loop forever, writing the packets we read to the writer(s), until
|
||||
we read a # or get a hangup */
|
||||
f = NULL;
|
||||
for(;;) {
|
||||
res = ast_waitfor(chan, 2000);
|
||||
if (!res) {
|
||||
ast_log(LOG_DEBUG, "One waitfor failed, trying another\n");
|
||||
/* Try one more time in case of masq */
|
||||
res = ast_waitfor(chan, 2000);
|
||||
if (!res) {
|
||||
ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (res < 0) {
|
||||
f = NULL;
|
||||
break;
|
||||
}
|
||||
f = ast_read(chan);
|
||||
if (!f)
|
||||
break;
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
/* write each format */
|
||||
for (x=0;x<fmtcnt;x++) {
|
||||
if (!others[x])
|
||||
break;
|
||||
res = ast_writestream(others[x], f);
|
||||
}
|
||||
|
||||
/* Silence Detection */
|
||||
if (maxsilence > 0) {
|
||||
dspsilence = 0;
|
||||
ast_dsp_silence(sildet, f, &dspsilence);
|
||||
if (dspsilence)
|
||||
totalsilence = dspsilence;
|
||||
else
|
||||
totalsilence = 0;
|
||||
|
||||
if (totalsilence > maxsilence) {
|
||||
/* Ended happily with silence */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
|
||||
ast_frfree(f);
|
||||
gotsilence = 1;
|
||||
outmsg=2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Exit on any error */
|
||||
if (res) {
|
||||
ast_log(LOG_WARNING, "Error writing frame\n");
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
} else if (f->frametype == AST_FRAME_VIDEO) {
|
||||
/* Write only once */
|
||||
ast_writestream(others[0], f);
|
||||
} else if (f->frametype == AST_FRAME_DTMF) {
|
||||
/* stop recording with any digit */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
|
||||
res = 't';
|
||||
outmsg = 2;
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
if (maxtime) {
|
||||
time(&end);
|
||||
if (maxtime < (end - start)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
|
||||
res = 't';
|
||||
outmsg=2;
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
if (end == start) time(&end);
|
||||
if (!f) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "User hung up\n");
|
||||
res = -1;
|
||||
outmsg=1;
|
||||
#if 0
|
||||
/* delete all the prepend files */
|
||||
for (x=0;x<fmtcnt;x++) {
|
||||
if (!others[x])
|
||||
break;
|
||||
ast_closestream(others[x]);
|
||||
ast_filedelete(prependfile, sfmt[x]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", prependfile, sfmt[x]);
|
||||
}
|
||||
*duration = end - start;
|
||||
#if 0
|
||||
if (outmsg > 1) {
|
||||
#else
|
||||
if (outmsg) {
|
||||
#endif
|
||||
struct ast_frame *fr;
|
||||
for (x=0;x<fmtcnt;x++) {
|
||||
snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]);
|
||||
realfiles[x] = ast_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0);
|
||||
if (!others[x] || !realfiles[x])
|
||||
break;
|
||||
if (totalsilence)
|
||||
ast_stream_rewind(others[x], totalsilence-200);
|
||||
else
|
||||
ast_stream_rewind(others[x], 200);
|
||||
ast_truncstream(others[x]);
|
||||
/* add the original file too */
|
||||
while ((fr = ast_readframe(realfiles[x]))) {
|
||||
ast_writestream(others[x],fr);
|
||||
}
|
||||
ast_closestream(others[x]);
|
||||
ast_closestream(realfiles[x]);
|
||||
ast_filerename(prependfile, recordfile, sfmt[x]);
|
||||
#if 0
|
||||
ast_verbose("Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x],prependfile,recordfile);
|
||||
#endif
|
||||
ast_filedelete(prependfile, sfmt[x]);
|
||||
}
|
||||
}
|
||||
if (rfmt) {
|
||||
if (ast_set_read_format(chan, rfmt)) {
|
||||
ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
|
||||
}
|
||||
}
|
||||
if (outmsg) {
|
||||
if (outmsg > 1) {
|
||||
/* Let them know it worked */
|
||||
ast_streamfile(chan, "auth-thankyou", chan->language);
|
||||
ast_waitstream(chan, "");
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int ast_lock_path(const char *path)
|
||||
{
|
||||
char *s;
|
||||
char *fs;
|
||||
int res;
|
||||
int fd;
|
||||
time_t start;
|
||||
s = alloca(strlen(path) + 10);
|
||||
fs = alloca(strlen(path) + 20);
|
||||
if (!fs || !s) {
|
||||
ast_log(LOG_WARNING, "Out of memory!\n");
|
||||
return -1;
|
||||
}
|
||||
snprintf(fs, strlen(path) + 19, "%s/%s-%08x", path, ".lock", rand());
|
||||
fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Unable to create lock file: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
|
||||
time(&start);
|
||||
while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5))
|
||||
usleep(1);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno));
|
||||
}
|
||||
unlink(fs);
|
||||
ast_log(LOG_DEBUG, "Locked path '%s'\n", path);
|
||||
return res;
|
||||
}
|
||||
|
||||
int ast_unlock_path(const char *path)
|
||||
{
|
||||
char *s;
|
||||
s = alloca(strlen(path) + 10);
|
||||
if (!s)
|
||||
return -1;
|
||||
snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
|
||||
ast_log(LOG_DEBUG, "Unlocked path '%s'\n", path);
|
||||
return unlink(s);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,19 +17,15 @@ USE_POSTGRES_VM_INTERFACE=0
|
||||
#APPS=app_dial.so app_playback.so app_directory.so app_intercom.so app_mp3.so
|
||||
APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_mp3.so\
|
||||
app_system.so app_echo.so app_record.so app_image.so app_url.so app_disa.so \
|
||||
app_qcall.so app_adsiprog.so app_getcpeid.so app_milliwatt.so \
|
||||
app_zapateller.so app_setcallerid.so app_festival.so \
|
||||
app_agi.so app_qcall.so app_adsiprog.so app_getcpeid.so app_milliwatt.so \
|
||||
app_zapateller.so app_datetime.so app_setcallerid.so app_festival.so \
|
||||
app_queue.so app_senddtmf.so app_parkandannounce.so app_striplsd.so \
|
||||
app_setcidname.so app_lookupcidname.so app_substring.so app_macro.so \
|
||||
app_authenticate.so app_softhangup.so app_lookupblacklist.so \
|
||||
app_waitforring.so app_privacy.so app_db.so app_chanisavail.so \
|
||||
app_enumlookup.so app_transfer.so app_setcidnum.so app_cdr.so \
|
||||
app_hasnewvoicemail.so app_sayunixtime.so app_cut.so app_read.so \
|
||||
app_setcdruserfield.so app_random.so app_ices.so app_eval.so \
|
||||
app_nbscat.so app_sendtext.so app_exec.so app_sms.so \
|
||||
app_groupcount.so app_txtcidname.so app_controlplayback.so \
|
||||
app_talkdetect.so app_alarmreceiver.so app_userevent.so app_verbose.so \
|
||||
app_test.so app_forkcdr.so
|
||||
app_setcdruserfield.so app_random.so
|
||||
|
||||
ifneq (${OSARCH},Darwin)
|
||||
APPS+=app_intercom.so
|
||||
@@ -37,11 +33,9 @@ endif
|
||||
|
||||
#APPS+=app_sql_postgres.so
|
||||
#APPS+=app_sql_odbc.so
|
||||
#APPS+=app_rpt.so
|
||||
|
||||
APPS+=$(shell if [ -f /usr/include/linux/zaptel.h ]; then echo "app_zapras.so app_meetme.so app_flash.so app_zapbarge.so app_zapscan.so" ; fi)
|
||||
APPS+=$(shell if [ -f /usr/local/include/zaptel.h ]; then echo "app_zapras.so app_meetme.so app_flash.so app_zapbarge.so app_zapscan.so" ; fi)
|
||||
APPS+=$(shell if [ -f /usr/include/osp/osp.h ]; then echo "app_osplookup.so" ; fi)
|
||||
#APPS+=$(shell if [ -f /usr/include/zap.h ]; then echo "app_rpt.so" ; fi)
|
||||
|
||||
CFLAGS+=-fPIC
|
||||
|
||||
@@ -66,7 +60,12 @@ app_rpt.so : app_rpt.o
|
||||
|
||||
install: all
|
||||
for x in $(APPS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
|
||||
rm -f $(DESTDIR)$(MODULES_DIR)/app_datetime.so
|
||||
|
||||
app_todd.o: app_todd.c
|
||||
gcc -pipe -O6 -g -Iinclude -I../include -D_REENTRANT -march=i586 -DDO_CRASH -c -o app_todd.o app_todd.c
|
||||
|
||||
app_todd.so: app_todd.o
|
||||
$(CC) $(SOLINK) -o $@ $< -L/usr/local/ssl/lib -lssl -lcrypto
|
||||
|
||||
app_voicemail.so : app_voicemail.o
|
||||
ifeq ($(USE_MYSQL_VM_INTERFACE),1)
|
||||
@@ -89,7 +88,7 @@ app_sql_odbc.so: app_sql_odbc.o
|
||||
$(CC) $(SOLINK) -o $@ $< -lodbc
|
||||
|
||||
look: look.c
|
||||
$(CC) -pipe -O6 -g look.c -o look -lncurses
|
||||
gcc -pipe -O6 -g look.c -o look -lncurses
|
||||
|
||||
ifneq ($(wildcard .depend),)
|
||||
include .depend
|
||||
@@ -99,6 +98,3 @@ depend: .depend
|
||||
|
||||
.depend:
|
||||
../mkdep $(CFLAGS) `ls *.c`
|
||||
|
||||
env:
|
||||
env
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/adsi.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@@ -30,6 +28,8 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "../asterisk.h"
|
||||
#include "../astconf.h"
|
||||
|
||||
@@ -178,7 +178,7 @@ static int process_token(void *out, char *src, int maxlen, int argtype)
|
||||
maxlen = strlen(src) - 1;
|
||||
memcpy(out, src, maxlen);
|
||||
((char *)out)[maxlen] = '\0';
|
||||
} else if (!ast_strlen_zero(src) && (src[0] == '\\')) {
|
||||
} else if (strlen(src) && (src[0] == '\\')) {
|
||||
if (!(argtype & ARG_NUMBER))
|
||||
return -1;
|
||||
/* Octal value */
|
||||
@@ -198,7 +198,7 @@ static int process_token(void *out, char *src, int maxlen, int argtype)
|
||||
/* Convert */
|
||||
*((unsigned int *)out) = htonl(*((unsigned int *)out));
|
||||
}
|
||||
} else if ((!ast_strlen_zero(src) && isdigit(src[0]))) {
|
||||
} else if ((strlen(src) && isdigit(src[0]))) {
|
||||
if (!(argtype & ARG_NUMBER))
|
||||
return -1;
|
||||
/* Hex value */
|
||||
@@ -666,7 +666,7 @@ static int showdisplay(char *buf, char *name, int id, char *args, struct adsi_sc
|
||||
}
|
||||
|
||||
buf[0] = id;
|
||||
buf[1] = (cmd << 6) | (disp->id & 0x3f);
|
||||
buf[1] = (cmd << 6) | (disp->id & 0x2f);
|
||||
buf[2] = ((line & 0x1f) << 3) | (flag & 0x7);
|
||||
return 3;
|
||||
}
|
||||
@@ -695,18 +695,6 @@ static int digitdirect(char *buf, char *name, int id, char *args, struct adsi_sc
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int clearcbone(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
|
||||
{
|
||||
char *tok;
|
||||
tok = get_token(&args, script, lineno);
|
||||
if (tok)
|
||||
ast_log(LOG_WARNING, "CLEARCB1 requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
|
||||
|
||||
buf[0] = id;
|
||||
buf[1] = 0;
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int digitcollect(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
|
||||
{
|
||||
char *tok;
|
||||
@@ -843,7 +831,6 @@ static struct adsi_key_cmd kcmds[] = {
|
||||
{ "VOICEMODE", 0x93 },
|
||||
/* Display call buffer 'n' */
|
||||
/* Clear call buffer 'n' */
|
||||
{ "CLEARCB1", 0x95, clearcbone },
|
||||
{ "DIGITCOLLECT", 0x96, digitcollect },
|
||||
{ "DIGITDIRECT", 0x96, digitdirect },
|
||||
{ "CLEAR", 0x97 },
|
||||
@@ -1363,7 +1350,7 @@ static struct adsi_script *compile_script(char *script)
|
||||
/* Strip comments */
|
||||
if (c)
|
||||
*c = '\0';
|
||||
if (!ast_strlen_zero(buf))
|
||||
if (strlen(buf))
|
||||
adsi_process(scr, buf, script, lineno);
|
||||
}
|
||||
}
|
||||
@@ -1448,7 +1435,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
|
||||
bytes = 0;
|
||||
/* Start with key definitions */
|
||||
for (x=0;x<scr->numkeys;x++) {
|
||||
if (bytes + scr->keys[x].retstrlen > 253) {
|
||||
if (bytes + scr->keys[x].retstrlen > 254) {
|
||||
/* Send what we've collected so far */
|
||||
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
|
||||
@@ -1472,7 +1459,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
|
||||
bytes = 0;
|
||||
/* Continue with the display messages */
|
||||
for (x=0;x<scr->numdisplays;x++) {
|
||||
if (bytes + scr->displays[x].datalen > 253) {
|
||||
if (bytes + scr->displays[x].datalen > 254) {
|
||||
/* Send what we've collected so far */
|
||||
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
|
||||
@@ -1496,7 +1483,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
|
||||
bytes = 0;
|
||||
/* Send subroutines */
|
||||
for (x=0;x<scr->numsubs;x++) {
|
||||
if (bytes + scr->subs[x].datalen > 253) {
|
||||
if (bytes + scr->subs[x].datalen > 254) {
|
||||
/* Send what we've collected so far */
|
||||
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
|
||||
@@ -1540,7 +1527,7 @@ static int adsi_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
if (!data || ast_strlen_zero(data))
|
||||
if (!data || !strlen(data))
|
||||
data = "asterisk.adsi";
|
||||
LOCAL_USER_ADD(u);
|
||||
if (!adsi_available(chan)) {
|
||||
|
||||
@@ -3,20 +3,15 @@
|
||||
*
|
||||
* Asterisk Gateway Interface
|
||||
*
|
||||
* Copyright (C) 1999-2004, Digium, Inc.
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
@@ -30,7 +25,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/poll.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
@@ -42,18 +36,33 @@
|
||||
#include <asterisk/app.h>
|
||||
#include <asterisk/dsp.h>
|
||||
#include <asterisk/musiconhold.h>
|
||||
#include <asterisk/manager.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/agi.h>
|
||||
#include "../asterisk.h"
|
||||
#include "../astconf.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#define MAX_ARGS 128
|
||||
#define MAX_COMMANDS 128
|
||||
|
||||
/* Recycle some stuff from the CLI interface */
|
||||
#define fdprintf agi_debug_cli
|
||||
#define fdprintf ast_cli
|
||||
|
||||
typedef struct agi_state {
|
||||
int fd; /* FD for general output */
|
||||
int audio; /* FD for audio output */
|
||||
int ctrl; /* FD for input control */
|
||||
} AGI;
|
||||
|
||||
typedef struct agi_command {
|
||||
/* Null terminated list of the words of the command */
|
||||
char *cmda[AST_MAX_CMD_LEN];
|
||||
/* Handler for the command (channel, AGI state, # of arguments, argument list).
|
||||
Returns RESULT_SHOWUSAGE for improper arguments */
|
||||
int (*handler)(struct ast_channel *chan, AGI *agi, int argc, char *argv[]);
|
||||
/* Summary of the command (< 60 characters) */
|
||||
char *summary;
|
||||
/* Detailed usage information */
|
||||
char *usage;
|
||||
} agi_command;
|
||||
|
||||
static char *tdesc = "Asterisk Gateway Interface (AGI)";
|
||||
|
||||
@@ -61,25 +70,16 @@ static char *app = "AGI";
|
||||
|
||||
static char *eapp = "EAGI";
|
||||
|
||||
static char *deadapp = "DeadAGI";
|
||||
|
||||
static char *synopsis = "Executes an AGI compliant application";
|
||||
static char *esynopsis = "Executes an EAGI compliant application";
|
||||
static char *deadsynopsis = "Executes AGI on a hungup channel";
|
||||
|
||||
static char *descrip =
|
||||
" [E|Dead]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
|
||||
"program on a channel. AGI allows Asterisk to launch external programs\n"
|
||||
" [E]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
|
||||
"program on a channel. AGI allows Asterisk to launch external programs\n"
|
||||
"written in any language to control a telephony channel, play audio,\n"
|
||||
"read DTMF digits, etc. by communicating with the AGI protocol on stdin\n"
|
||||
"and stdout.\n"
|
||||
"Returns -1 on hangup (except for DeadAGI) or if application requested\n"
|
||||
" hangup, or 0 on non-hangup exit. \n"
|
||||
"Using 'EAGI' provides enhanced AGI, with incoming audio available out of band"
|
||||
"on file descriptor 3\n\n"
|
||||
"Use the CLI command 'show agi' to list available agi commands\n";
|
||||
|
||||
static int agidebug = 0;
|
||||
"and stdout. Returns -1 on hangup or if application requested hangup, or\n"
|
||||
"0 on non-hangup exit. Using 'EAGI' provides enhanced AGI, with audio\n"
|
||||
"available out of band on file descriptor 3\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -88,113 +88,7 @@ LOCAL_USER_DECL;
|
||||
|
||||
#define TONE_BLOCK_SIZE 200
|
||||
|
||||
/* Max time to connect to an AGI remote host */
|
||||
#define MAX_AGI_CONNECT 2000
|
||||
|
||||
#define AGI_PORT 4573
|
||||
|
||||
static void agi_debug_cli(int fd, char *fmt, ...)
|
||||
{
|
||||
char *stuff;
|
||||
int res = 0;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
res = vasprintf(&stuff, fmt, ap);
|
||||
va_end(ap);
|
||||
if (res == -1) {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
} else {
|
||||
if (agidebug)
|
||||
ast_verbose("AGI Tx >> %s", stuff);
|
||||
ast_carefulwrite(fd, stuff, strlen(stuff), 100);
|
||||
free(stuff);
|
||||
}
|
||||
}
|
||||
|
||||
static int launch_netscript(char *agiurl, char *argv[], int *fds, int *efd, int *opid)
|
||||
{
|
||||
int s;
|
||||
int flags;
|
||||
struct pollfd pfds[1];
|
||||
char *host;
|
||||
char *c; int port = AGI_PORT;
|
||||
char *script = "";
|
||||
struct sockaddr_in sin;
|
||||
struct hostent *hp;
|
||||
struct ast_hostent ahp;
|
||||
ast_log(LOG_DEBUG, "Blah\n");
|
||||
host = ast_strdupa(agiurl + 6);
|
||||
if (!host)
|
||||
return -1;
|
||||
/* Strip off any script name */
|
||||
if ((c = strchr(host, '/'))) {
|
||||
*c = '\0';
|
||||
c++;
|
||||
script = c;
|
||||
}
|
||||
if ((c = strchr(host, ':'))) {
|
||||
*c = '\0';
|
||||
c++;
|
||||
port = atoi(c);
|
||||
}
|
||||
if (efd) {
|
||||
ast_log(LOG_WARNING, "AGI URI's don't support Enhanced AGI yet\n");
|
||||
return -1;
|
||||
}
|
||||
hp = ast_gethostbyname(host, &ahp);
|
||||
if (!hp) {
|
||||
ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host);
|
||||
return -1;
|
||||
}
|
||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (s < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
flags = fcntl(s, F_GETFL);
|
||||
if (flags < 0) {
|
||||
ast_log(LOG_WARNING, "Fcntl(F_GETFL) failed: %s\n", strerror(errno));
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
|
||||
ast_log(LOG_WARNING, "Fnctl(F_SETFL) failed: %s\n", strerror(errno));
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(port);
|
||||
memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
|
||||
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) && (errno != EINPROGRESS)) {
|
||||
ast_log(LOG_WARNING, "Connect failed with unexpected error: %s\n", strerror(errno));
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
pfds[0].fd = s;
|
||||
pfds[0].events = POLLOUT;
|
||||
if (poll(pfds, 1, MAX_AGI_CONNECT) != 1) {
|
||||
ast_log(LOG_WARNING, "Connect to '%s' failed!\n", agiurl);
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
if (write(s, "agi_network: yes\n", strlen("agi_network: yes\n")) < 0) {
|
||||
ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
ast_log(LOG_DEBUG, "Wow, connected!\n");
|
||||
/* Send the script parameter */
|
||||
if (!ast_strlen_zero(script))
|
||||
fdprintf(s, "agi_network_script: %s\n", script);
|
||||
fds[0] = s;
|
||||
fds[1] = s;
|
||||
*opid = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int launch_script(char *script, char *argv[], int *fds, int *efd, int *opid)
|
||||
static int launch_script(char *script, char *args, int *fds, int *efd, int *opid)
|
||||
{
|
||||
char tmp[256];
|
||||
int pid;
|
||||
@@ -203,10 +97,6 @@ static int launch_script(char *script, char *argv[], int *fds, int *efd, int *op
|
||||
int audio[2];
|
||||
int x;
|
||||
int res;
|
||||
|
||||
if (!strncasecmp(script, "agi://", 6))
|
||||
return launch_netscript(script, argv, fds, efd, opid);
|
||||
|
||||
if (script[0] != '/') {
|
||||
snprintf(tmp, sizeof(tmp), "%s/%s", (char *)ast_config_AST_AGI_DIR, script);
|
||||
script = tmp;
|
||||
@@ -262,7 +152,7 @@ static int launch_script(char *script, char *argv[], int *fds, int *efd, int *op
|
||||
for (x=STDERR_FILENO + 2;x<1024;x++)
|
||||
close(x);
|
||||
/* Execute script */
|
||||
execv(script, argv);
|
||||
execl(script, script, args, (char *)NULL);
|
||||
/* Can't use ast_log since FD's are closed */
|
||||
fprintf(stderr, "Failed to execute '%s': %s\n", script, strerror(errno));
|
||||
exit(1);
|
||||
@@ -435,7 +325,8 @@ static int handle_streamfile(struct ast_channel *chan, AGI *agi, int argc, char
|
||||
fs = ast_openstream(chan, argv[2], chan->language);
|
||||
if(!fs){
|
||||
fdprintf(agi->fd, "200 result=%d endpos=%ld\n", 0, sample_offset);
|
||||
return RESULT_SUCCESS;
|
||||
ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]);
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
ast_seekstream(fs, 0, SEEK_END);
|
||||
max_length = ast_tellstream(fs);
|
||||
@@ -465,9 +356,6 @@ static int handle_streamfile(struct ast_channel *chan, AGI *agi, int argc, char
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
/*--- handle_saynumber: Say number in various language syntaxes ---*/
|
||||
/* Need to add option for gender here as well. Coders wanted */
|
||||
/* While waiting, we're sending a (char *) NULL. */
|
||||
static int handle_saynumber(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
|
||||
{
|
||||
int res;
|
||||
@@ -476,7 +364,7 @@ static int handle_saynumber(struct ast_channel *chan, AGI *agi, int argc, char *
|
||||
return RESULT_SHOWUSAGE;
|
||||
if (sscanf(argv[2], "%i", &num) != 1)
|
||||
return RESULT_SHOWUSAGE;
|
||||
res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio, agi->ctrl);
|
||||
res = ast_say_number_full(chan, num, argv[3], chan->language, agi->audio, agi->ctrl);
|
||||
if (res == 1)
|
||||
return RESULT_SUCCESS;
|
||||
fdprintf(agi->fd, "200 result=%d\n", res);
|
||||
@@ -490,12 +378,10 @@ static int handle_saydigits(struct ast_channel *chan, AGI *agi, int argc, char *
|
||||
{
|
||||
int res;
|
||||
int num;
|
||||
|
||||
if (argc != 4)
|
||||
return RESULT_SHOWUSAGE;
|
||||
if (sscanf(argv[2], "%i", &num) != 1)
|
||||
return RESULT_SHOWUSAGE;
|
||||
|
||||
res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
|
||||
if (res == 1) /* New command */
|
||||
return RESULT_SUCCESS;
|
||||
@@ -506,41 +392,6 @@ static int handle_saydigits(struct ast_channel *chan, AGI *agi, int argc, char *
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
static int handle_saytime(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
|
||||
{
|
||||
int res;
|
||||
int num;
|
||||
if (argc != 4)
|
||||
return RESULT_SHOWUSAGE;
|
||||
if (sscanf(argv[2], "%i", &num) != 1)
|
||||
return RESULT_SHOWUSAGE;
|
||||
res = ast_say_time(chan, num, argv[3], chan->language);
|
||||
if (res == 1)
|
||||
return RESULT_SUCCESS;
|
||||
fdprintf(agi->fd, "200 result=%d\n", res);
|
||||
if (res >= 0)
|
||||
return RESULT_SUCCESS;
|
||||
else
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
static int handle_sayphonetic(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
|
||||
{
|
||||
int res;
|
||||
|
||||
if (argc != 4)
|
||||
return RESULT_SHOWUSAGE;
|
||||
|
||||
res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
|
||||
if (res == 1) /* New command */
|
||||
return RESULT_SUCCESS;
|
||||
fdprintf(agi->fd, "200 result=%d\n", res);
|
||||
if (res >= 0)
|
||||
return RESULT_SUCCESS;
|
||||
else
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
static int handle_getdata(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
|
||||
{
|
||||
int res;
|
||||
@@ -557,8 +408,8 @@ static int handle_getdata(struct ast_channel *chan, AGI *agi, int argc, char *ar
|
||||
return RESULT_SUCCESS;
|
||||
else if (res == 1)
|
||||
fdprintf(agi->fd, "200 result=%s (timeout)\n", data);
|
||||
else if (res < 0 )
|
||||
fdprintf(agi->fd, "200 result=-1\n");
|
||||
else if (res < 0 )
|
||||
fdprintf(agi->fd, "200 result=-1\n");
|
||||
else
|
||||
fdprintf(agi->fd, "200 result=%s\n", data);
|
||||
if (res >= 0)
|
||||
@@ -674,8 +525,6 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, char
|
||||
if (!fs) {
|
||||
res = -1;
|
||||
fdprintf(agi->fd, "200 result=%d (writefile)\n", res);
|
||||
if (sildet)
|
||||
ast_dsp_free(sildet);
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -692,16 +541,12 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, char
|
||||
if (res < 0) {
|
||||
ast_closestream(fs);
|
||||
fdprintf(agi->fd, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset);
|
||||
if (sildet)
|
||||
ast_dsp_free(sildet);
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
fdprintf(agi->fd, "200 result=%d (hangup) endpos=%ld\n", 0, sample_offset);
|
||||
ast_closestream(fs);
|
||||
if (sildet)
|
||||
ast_dsp_free(sildet);
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
switch(f->frametype) {
|
||||
@@ -712,8 +557,6 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, char
|
||||
fdprintf(agi->fd, "200 result=%d (dtmf) endpos=%ld\n", f->subclass, sample_offset);
|
||||
ast_closestream(fs);
|
||||
ast_frfree(f);
|
||||
if (sildet)
|
||||
ast_dsp_free(sildet);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
break;
|
||||
@@ -749,7 +592,6 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, char
|
||||
if (gotsilence) {
|
||||
ast_stream_rewind(fs, silence-1000);
|
||||
ast_truncstream(fs);
|
||||
sample_offset = ast_tellstream(fs);
|
||||
}
|
||||
fdprintf(agi->fd, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset);
|
||||
ast_closestream(fs);
|
||||
@@ -793,17 +635,15 @@ static int handle_hangup(struct ast_channel *chan, AGI *agi, int argc, char **ar
|
||||
return RESULT_SUCCESS;
|
||||
} else if (argc==2) {
|
||||
/* one argument: look for info on the specified channel */
|
||||
c = ast_channel_walk_locked(NULL);
|
||||
c = ast_channel_walk(NULL);
|
||||
while (c) {
|
||||
if (strcasecmp(argv[1],c->name)==0) {
|
||||
/* we have a matching channel */
|
||||
ast_softhangup(c,AST_SOFTHANGUP_EXPLICIT);
|
||||
fdprintf(agi->fd, "200 result=1\n");
|
||||
ast_mutex_unlock(&c->lock);
|
||||
ast_softhangup(c,AST_SOFTHANGUP_EXPLICIT);
|
||||
fdprintf(agi->fd, "200 result=1\n");
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
ast_mutex_unlock(&c->lock);
|
||||
c = ast_channel_walk_locked(c);
|
||||
c = ast_channel_walk(c);
|
||||
}
|
||||
/* if we get this far no channel name matched the argument given */
|
||||
fdprintf(agi->fd, "200 result=-1\n");
|
||||
@@ -842,35 +682,34 @@ static int handle_setcallerid(struct ast_channel *chan, AGI *agi, int argc, char
|
||||
if (argv[2])
|
||||
ast_set_callerid(chan, argv[2], 0);
|
||||
|
||||
fdprintf(agi->fd, "200 result=1\n");
|
||||
/* strncpy(chan->callerid, argv[2], sizeof(chan->callerid)-1);
|
||||
*/ fdprintf(agi->fd, "200 result=1\n");
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int handle_channelstatus(struct ast_channel *chan, AGI *agi, int argc, char **argv)
|
||||
{
|
||||
struct ast_channel *c;
|
||||
if (argc==2) {
|
||||
/* no argument: supply info on the current channel */
|
||||
fdprintf(agi->fd, "200 result=%d\n", chan->_state);
|
||||
return RESULT_SUCCESS;
|
||||
} else if (argc==3) {
|
||||
/* one argument: look for info on the specified channel */
|
||||
c = ast_channel_walk_locked(NULL);
|
||||
while (c) {
|
||||
if (strcasecmp(argv[2],c->name)==0) {
|
||||
fdprintf(agi->fd, "200 result=%d\n", c->_state);
|
||||
ast_mutex_unlock(&c->lock);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
ast_mutex_unlock(&c->lock);
|
||||
c = ast_channel_walk_locked(c);
|
||||
}
|
||||
/* if we get this far no channel name matched the argument given */
|
||||
fdprintf(agi->fd, "200 result=-1\n");
|
||||
return RESULT_SUCCESS;
|
||||
} else {
|
||||
return RESULT_SHOWUSAGE;
|
||||
}
|
||||
struct ast_channel *c;
|
||||
if (argc==2) {
|
||||
/* no argument: supply info on the current channel */
|
||||
fdprintf(agi->fd, "200 result=%d\n", chan->_state);
|
||||
return RESULT_SUCCESS;
|
||||
} else if (argc==3) {
|
||||
/* one argument: look for info on the specified channel */
|
||||
c = ast_channel_walk(NULL);
|
||||
while (c) {
|
||||
if (strcasecmp(argv[2],c->name)==0) {
|
||||
fdprintf(agi->fd, "200 result=%d\n", c->_state);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
c = ast_channel_walk(c);
|
||||
}
|
||||
/* if we get this far no channel name matched the argument given */
|
||||
fdprintf(agi->fd, "200 result=-1\n");
|
||||
return RESULT_SUCCESS;
|
||||
} else {
|
||||
return RESULT_SHOWUSAGE;
|
||||
}
|
||||
}
|
||||
|
||||
static int handle_setvariable(struct ast_channel *chan, AGI *agi, int argc, char **argv)
|
||||
@@ -886,10 +725,10 @@ static int handle_getvariable(struct ast_channel *chan, AGI *agi, int argc, char
|
||||
{
|
||||
char *tempstr;
|
||||
|
||||
if ((tempstr = pbx_builtin_getvar_helper(chan, argv[2])))
|
||||
fdprintf(agi->fd, "200 result=1 (%s)\n", tempstr);
|
||||
if ((tempstr = pbx_builtin_getvar_helper(chan, argv[2])) )
|
||||
fdprintf(agi->fd, "200 result=1 (%s)\n", tempstr);
|
||||
else
|
||||
fdprintf(agi->fd, "200 result=0\n");
|
||||
fdprintf(agi->fd, "200 result=0\n");
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
@@ -937,9 +776,9 @@ static int handle_dbget(struct ast_channel *chan, AGI *agi, int argc, char **arg
|
||||
return RESULT_SHOWUSAGE;
|
||||
res = ast_db_get(argv[2], argv[3], tmp, sizeof(tmp));
|
||||
if (res)
|
||||
fdprintf(agi->fd, "200 result=0\n");
|
||||
fdprintf(agi->fd, "200 result=0\n");
|
||||
else
|
||||
fdprintf(agi->fd, "200 result=1 (%s)\n", tmp);
|
||||
fdprintf(agi->fd, "200 result=1 (%s)\n", tmp);
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
@@ -951,9 +790,9 @@ static int handle_dbput(struct ast_channel *chan, AGI *agi, int argc, char **arg
|
||||
return RESULT_SHOWUSAGE;
|
||||
res = ast_db_put(argv[2], argv[3], argv[4]);
|
||||
if (res)
|
||||
fdprintf(agi->fd, "200 result=0\n");
|
||||
fdprintf(agi->fd, "200 result=0\n");
|
||||
else
|
||||
fdprintf(agi->fd, "200 result=1\n");
|
||||
fdprintf(agi->fd, "200 result=1\n");
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
@@ -989,38 +828,6 @@ static int handle_dbdeltree(struct ast_channel *chan, AGI *agi, int argc, char *
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static char debug_usage[] =
|
||||
"Usage: agi debug\n"
|
||||
" Enables dumping of AGI transactions for debugging purposes\n";
|
||||
|
||||
static char no_debug_usage[] =
|
||||
"Usage: agi no debug\n"
|
||||
" Disables dumping of AGI transactions for debugging purposes\n";
|
||||
|
||||
static int agi_do_debug(int fd, int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
return RESULT_SHOWUSAGE;
|
||||
agidebug = 1;
|
||||
ast_cli(fd, "AGI Debugging Enabled\n");
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int agi_no_debug(int fd, int argc, char *argv[])
|
||||
{
|
||||
if (argc != 3)
|
||||
return RESULT_SHOWUSAGE;
|
||||
agidebug = 0;
|
||||
ast_cli(fd, "AGI Debugging Disabled\n");
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static struct ast_cli_entry cli_debug =
|
||||
{ { "agi", "debug", NULL }, agi_do_debug, "Enable AGI debugging", debug_usage };
|
||||
|
||||
static struct ast_cli_entry cli_no_debug =
|
||||
{ { "agi", "no", "debug", NULL }, agi_no_debug, "Disable AGI debugging", no_debug_usage };
|
||||
|
||||
static int handle_noop(struct ast_channel *chan, AGI *agi, int arg, char *argv[])
|
||||
{
|
||||
fdprintf(agi->fd, "200 result=0\n");
|
||||
@@ -1182,21 +989,6 @@ static char usage_saydigits[] =
|
||||
" being pressed, or the ASCII numerical value of the digit if one was pressed or\n"
|
||||
" -1 on error/hangup.\n";
|
||||
|
||||
static char usage_saytime[] =
|
||||
" Usage: SAY TIME <time> <escape digits>\n"
|
||||
" Say a given time, returning early if any of the given DTMF digits are\n"
|
||||
" received on the channel. <time> is number of seconds elapsed since 00:00:00\n"
|
||||
" on January 1, 1970, Coordinated Universal Time (UTC). Returns 0 if playback\n"
|
||||
" completes without a digit being pressed, or the ASCII numerical value of the\n"
|
||||
" digit if one was pressed or -1 on error/hangup.\n";
|
||||
|
||||
static char usage_sayphonetic[] =
|
||||
" Usage: SAY PHONETIC <string> <escape digits>\n"
|
||||
" Say a given character string with phonetics, returning early if any of the given DTMF digits\n"
|
||||
" are received on the channel. Returns 0 if playback completes without a digit\n"
|
||||
" being pressed, or the ASCII numerical value of the digit if one was pressed or\n"
|
||||
" -1 on error/hangup.\n";
|
||||
|
||||
static char usage_getdata[] =
|
||||
" Usage: GET DATA <file to be streamed> [timeout] [max digits]\n"
|
||||
" Stream the given file, and recieve DTMF data. Returns the digits recieved\n"
|
||||
@@ -1236,7 +1028,7 @@ static char usage_noop[] =
|
||||
" Usage: NOOP\n"
|
||||
" Does nothing.\n";
|
||||
|
||||
static agi_command commands[MAX_COMMANDS] = {
|
||||
static agi_command commands[] = {
|
||||
{ { "answer", NULL }, handle_answer, "Asserts answer", usage_answer },
|
||||
{ { "wait", "for", "digit", NULL }, handle_waitfordigit, "Waits for a digit to be pressed", usage_waitfordigit },
|
||||
{ { "send", "text", NULL }, handle_sendtext, "Sends text to channels supporting it", usage_sendtext },
|
||||
@@ -1246,8 +1038,6 @@ static agi_command commands[MAX_COMMANDS] = {
|
||||
{ { "send", "image", NULL }, handle_sendimage, "Sends images to channels supporting it", usage_sendimage },
|
||||
{ { "say", "digits", NULL }, handle_saydigits, "Says a given digit string", usage_saydigits },
|
||||
{ { "say", "number", NULL }, handle_saynumber, "Says a given number", usage_saynumber },
|
||||
{ { "say", "phonetic", NULL }, handle_sayphonetic, "Says a given character string with phonetics", usage_sayphonetic },
|
||||
{ { "say", "time", NULL }, handle_saytime, "Says a given time", usage_saytime },
|
||||
{ { "get", "data", NULL }, handle_getdata, "Gets data on a channel", usage_getdata },
|
||||
{ { "set", "context", NULL }, handle_setcontext, "Sets channel context", usage_setcontext },
|
||||
{ { "set", "extension", NULL }, handle_setextension, "Changes channel extension", usage_setextension },
|
||||
@@ -1269,18 +1059,15 @@ static agi_command commands[MAX_COMMANDS] = {
|
||||
{ { "set", "music", NULL }, handle_setmusic, "Enable/Disable Music on hold generator", usage_setmusic }
|
||||
};
|
||||
|
||||
static void join(char *s, size_t len, char *w[])
|
||||
static void join(char *s, int len, char *w[])
|
||||
{
|
||||
int x;
|
||||
/* Join words into a string */
|
||||
if (!s) {
|
||||
return;
|
||||
}
|
||||
s[0] = '\0';
|
||||
strcpy(s, "");
|
||||
for (x=0;w[x];x++) {
|
||||
if (x)
|
||||
strncat(s, " ", len - strlen(s) - 1);
|
||||
strncat(s, w[x], len - strlen(s) - 1);
|
||||
strncat(s, " ", len - strlen(s));
|
||||
strncat(s, w[x], len - strlen(s));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1293,7 +1080,6 @@ static int help_workhorse(int fd, char *match[])
|
||||
if (match)
|
||||
join(matchstr, sizeof(matchstr), match);
|
||||
for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) {
|
||||
if (!commands[x].cmda[0]) break;
|
||||
e = &commands[x];
|
||||
if (e)
|
||||
join(fullcmd, sizeof(fullcmd), e->cmda);
|
||||
@@ -1310,42 +1096,12 @@ static int help_workhorse(int fd, char *match[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
int agi_register(agi_command *agi)
|
||||
{
|
||||
int x;
|
||||
for (x=0;x<MAX_COMMANDS - 1;x++) {
|
||||
if (commands[x].cmda[0] == agi->cmda[0]) {
|
||||
ast_log(LOG_WARNING, "Command already registered!\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
for (x=0;x<MAX_COMMANDS - 1;x++) {
|
||||
if (!commands[x].cmda[0]) {
|
||||
commands[x] = *agi;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ast_log(LOG_WARNING, "No more room for new commands!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void agi_unregister(agi_command *agi)
|
||||
{
|
||||
int x;
|
||||
for (x=0;x<MAX_COMMANDS - 1;x++) {
|
||||
if (commands[x].cmda[0] == agi->cmda[0]) {
|
||||
memset(&commands[x], 0, sizeof(agi_command));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static agi_command *find_command(char *cmds[], int exact)
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int match;
|
||||
for (x=0;x < sizeof(commands) / sizeof(commands[0]);x++) {
|
||||
if (!commands[x].cmda[0]) break;
|
||||
/* start optimistic */
|
||||
match = 1;
|
||||
for (y=0;match && cmds[y]; y++) {
|
||||
@@ -1458,10 +1214,6 @@ static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf)
|
||||
fdprintf(agi->fd, c->usage);
|
||||
fdprintf(agi->fd, "520 End of proper usage.\n");
|
||||
break;
|
||||
case AST_PBX_KEEPALIVE:
|
||||
/* We've been asked to keep alive, so do so */
|
||||
return AST_PBX_KEEPALIVE;
|
||||
break;
|
||||
case RESULT_FAILURE:
|
||||
/* They've already given the failure. We've been hung up on so handle this
|
||||
appropriately */
|
||||
@@ -1473,7 +1225,7 @@ static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf)
|
||||
return 0;
|
||||
}
|
||||
#define RETRY 3
|
||||
static int run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int dead)
|
||||
static int run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid)
|
||||
{
|
||||
struct ast_channel *c;
|
||||
int outfd;
|
||||
@@ -1482,22 +1234,19 @@ static int run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, i
|
||||
struct ast_frame *f;
|
||||
char buf[2048];
|
||||
FILE *readf;
|
||||
/* how many times we'll retry if ast_waitfor_nandfs will return without either
|
||||
channel or file descriptor in case select is interrupted by a system call (EINTR) */
|
||||
//how many times we'll retry if ast_waitfor_nandfs will return without either channel or file descriptor in case select is interrupted by a system call (EINTR)
|
||||
int retry = RETRY;
|
||||
|
||||
if (!(readf = fdopen(agi->ctrl, "r"))) {
|
||||
ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n");
|
||||
if (pid > -1)
|
||||
kill(pid, SIGHUP);
|
||||
close(agi->ctrl);
|
||||
kill(pid, SIGHUP);
|
||||
return -1;
|
||||
}
|
||||
setlinebuf(readf);
|
||||
setup_env(chan, request, agi->fd, (agi->audio > -1));
|
||||
for (;;) {
|
||||
ms = -1;
|
||||
c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
|
||||
c = ast_waitfor_nandfds(&chan, 1, &agi->ctrl, 1, NULL, &outfd, &ms);
|
||||
if (c) {
|
||||
retry = RETRY;
|
||||
/* Idle the channel until we get a command */
|
||||
@@ -1529,11 +1278,10 @@ static int run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, i
|
||||
/* get rid of trailing newline, if any */
|
||||
if (*buf && buf[strlen(buf) - 1] == '\n')
|
||||
buf[strlen(buf) - 1] = 0;
|
||||
if (agidebug)
|
||||
ast_verbose("AGI Rx << %s\n", buf);
|
||||
|
||||
returnstatus |= agi_handle_command(chan, agi, buf);
|
||||
/* If the handle_command returns -1, we need to stop */
|
||||
if ((returnstatus < 0) || (returnstatus == AST_PBX_KEEPALIVE)) {
|
||||
if (returnstatus < 0) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -1597,7 +1345,6 @@ static int handle_dumpagihtml(int fd, int argc, char *argv[]) {
|
||||
|
||||
for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) {
|
||||
char *stringp=NULL;
|
||||
if (!commands[x].cmda[0]) break;
|
||||
e = &commands[x];
|
||||
if (e)
|
||||
join(fullcmd, sizeof(fullcmd), e->cmda);
|
||||
@@ -1630,47 +1377,52 @@ static int handle_dumpagihtml(int fd, int argc, char *argv[]) {
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int agi_exec_full(struct ast_channel *chan, void *data, int enhanced, int dead)
|
||||
static int agi_exec_full(struct ast_channel *chan, void *data, int enhanced)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *argv[MAX_ARGS];
|
||||
char buf[2048]="";
|
||||
char *tmp = (char *)buf;
|
||||
int argc = 0;
|
||||
char *args,*ringy;
|
||||
char tmp[256];
|
||||
int fds[2];
|
||||
int efd = -1;
|
||||
int pid;
|
||||
char *stringp;
|
||||
char *stringp=tmp;
|
||||
AGI agi;
|
||||
if (!data || ast_strlen_zero(data)) {
|
||||
if (!data || !strlen(data)) {
|
||||
ast_log(LOG_WARNING, "AGI requires an argument (script)\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(buf, data, sizeof(buf) - 1);
|
||||
|
||||
|
||||
memset(&agi, 0, sizeof(agi));
|
||||
while ((stringp = strsep(&tmp, "|"))) {
|
||||
argv[argc++] = stringp;
|
||||
}
|
||||
argv[argc] = NULL;
|
||||
|
||||
strncpy(tmp, data, sizeof(tmp)-1);
|
||||
strsep(&stringp, "|");
|
||||
args = strsep(&stringp, "|");
|
||||
ringy = strsep(&stringp,"|");
|
||||
if (!args)
|
||||
args = "";
|
||||
LOCAL_USER_ADD(u);
|
||||
#if 0
|
||||
/* Answer if need be */
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
if (ringy) { /* if for ringing first */
|
||||
/* a little ringy-dingy first */
|
||||
ast_indicate(chan, AST_CONTROL_RINGING);
|
||||
sleep(3);
|
||||
}
|
||||
if (ast_answer(chan)) {
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, &pid);
|
||||
res = launch_script(tmp, args, fds, enhanced ? &efd : NULL, &pid);
|
||||
if (!res) {
|
||||
agi.fd = fds[1];
|
||||
agi.ctrl = fds[0];
|
||||
agi.audio = efd;
|
||||
res = run_agi(chan, argv[0], &agi, pid, dead);
|
||||
res = run_agi(chan, tmp, &agi, pid);
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
if (efd > -1)
|
||||
close(efd);
|
||||
@@ -1681,23 +1433,19 @@ static int agi_exec_full(struct ast_channel *chan, void *data, int enhanced, int
|
||||
|
||||
static int agi_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
if (chan->_softhangup)
|
||||
ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
|
||||
return agi_exec_full(chan, data, 0, 0);
|
||||
return agi_exec_full(chan, data, 0);
|
||||
}
|
||||
|
||||
static int eagi_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int readformat;
|
||||
int res;
|
||||
if (chan->_softhangup)
|
||||
ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
|
||||
readformat = chan->readformat;
|
||||
if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
|
||||
ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
|
||||
return -1;
|
||||
}
|
||||
res = agi_exec_full(chan, data, 1, 0);
|
||||
res = agi_exec_full(chan, data, 1);
|
||||
if (!res) {
|
||||
if (ast_set_read_format(chan, readformat)) {
|
||||
ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat));
|
||||
@@ -1706,11 +1454,6 @@ static int eagi_exec(struct ast_channel *chan, void *data)
|
||||
return res;
|
||||
}
|
||||
|
||||
static int deadagi_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
return agi_exec_full(chan, data, 0, 1);
|
||||
}
|
||||
|
||||
static char showagi_help[] =
|
||||
"Usage: show agi [topic]\n"
|
||||
" When called with a topic as an argument, displays usage\n"
|
||||
@@ -1733,10 +1476,7 @@ int unload_module(void)
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
ast_cli_unregister(&showagi);
|
||||
ast_cli_unregister(&dumpagihtml);
|
||||
ast_cli_unregister(&cli_debug);
|
||||
ast_cli_unregister(&cli_no_debug);
|
||||
ast_unregister_application(eapp);
|
||||
ast_unregister_application(deadapp);
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
@@ -1744,10 +1484,7 @@ int load_module(void)
|
||||
{
|
||||
ast_cli_register(&showagi);
|
||||
ast_cli_register(&dumpagihtml);
|
||||
ast_cli_register(&cli_debug);
|
||||
ast_cli_register(&cli_no_debug);
|
||||
ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
|
||||
ast_register_application(eapp, eagi_exec, esynopsis, descrip);
|
||||
ast_register_application(eapp, eagi_exec, synopsis, descrip);
|
||||
return ast_register_application(app, agi_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
@@ -1,858 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Central Station Alarm receiver for Ademco Contact ID
|
||||
*
|
||||
* Copyright (C) 2004 Steve Rodgers
|
||||
*
|
||||
* Steve Rodgers <hwstar@rodgers.sdcoxmail.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*
|
||||
* *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***
|
||||
*
|
||||
* Use at your own risk. Please consult the GNU GPL license document included with Asterisk details. *
|
||||
*
|
||||
* *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***
|
||||
*
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/ulaw.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <asterisk/dsp.h>
|
||||
#include <asterisk/config.h>
|
||||
#include <asterisk/localtime.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <asterisk/astdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define ALMRCV_CONFIG "alarmreceiver.conf"
|
||||
#define ADEMCO_CONTACT_ID "ADEMCO_CONTACT_ID"
|
||||
|
||||
struct event_node{
|
||||
char data[17];
|
||||
struct event_node *next;
|
||||
};
|
||||
|
||||
typedef struct event_node event_node_t;
|
||||
|
||||
static char *tdesc = "Alarm Receiver for Asterisk";
|
||||
|
||||
static char *app = "AlarmReceiver";
|
||||
|
||||
static char *synopsis = "Provide support for receving alarm reports from a burglar or fire alarm panel";
|
||||
static char *descrip =
|
||||
"Alarm receiver application for Asterisk. Only 1 signalling format is supported at this time:\n"
|
||||
"Ademco Contact ID. This application should be called whenever there is an alarm panel calling in\n"
|
||||
"to dump its events. The application will handshake with the alarm panel, and receive events,\n"
|
||||
"validate them, handshake them, and store them until the panel hangs up. Once the panel hangs up,\n"
|
||||
"the application will run the command line specified by the eventcmd setting in alarmreceiver.conf\n"
|
||||
"and pipe the events to the standard input of the application. Alarmreceiver.conf also contains settings\n"
|
||||
"for DTMF timing, and for the loudness of the acknowledgement tones.\n";
|
||||
|
||||
/* Config Variables */
|
||||
|
||||
static int fdtimeout = 2000;
|
||||
static int sdtimeout = 200;
|
||||
static int toneloudness = 4096;
|
||||
static int log_individual_events = 0;
|
||||
static char event_spool_dir[128] = {'\0'};
|
||||
static char event_app[128] = {'\0'};
|
||||
static char db_family[128] = {'\0'};
|
||||
static char time_stamp_format[128] = {"%a %b %d, %Y @ %H:%M:%S %Z"};
|
||||
|
||||
|
||||
/* Misc variables */
|
||||
|
||||
|
||||
static char event_file[14] = "/event-XXXXXX";
|
||||
|
||||
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
/*
|
||||
* Attempt to access a database variable and increment it,
|
||||
* provided that the user defined db-family in alarmreceiver.conf
|
||||
* The alarmreceiver app will write statistics to a few variables
|
||||
* in this family if it is defined. If the new key doesn't exist in the
|
||||
* family, then create it and set its value to 1.
|
||||
*/
|
||||
|
||||
static void database_increment( char *key )
|
||||
{
|
||||
int res = 0;
|
||||
unsigned v;
|
||||
char value[16];
|
||||
|
||||
|
||||
if(!strlen(db_family))
|
||||
return; /* If not defined, don't do anything */
|
||||
|
||||
res = ast_db_get(db_family, key, value, sizeof(value) - 1);
|
||||
|
||||
if(res){
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Creating database entry %s and setting to 1\n", key);
|
||||
/* Guess we have to create it */
|
||||
res = ast_db_put(db_family, key, "1");
|
||||
return;
|
||||
}
|
||||
|
||||
sscanf(value, "%u", &v);
|
||||
v++;
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: New value for %s: %u\n", key, v);
|
||||
|
||||
snprintf(value, sizeof(value), "%u", v);
|
||||
|
||||
res = ast_db_put(db_family, key, value);
|
||||
|
||||
if((res)&&(option_verbose >= 4))
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: database_increment write error");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Build a MuLaw data block for a single frequency tone
|
||||
*/
|
||||
|
||||
static void make_tone_burst(unsigned char *data, float freq, float loudness, int len, int *x)
|
||||
{
|
||||
int i;
|
||||
float val;
|
||||
|
||||
for(i = 0; i < len; i++){
|
||||
val = loudness * sin((freq * 2.0 * M_PI * (*x)++)/8000.0);
|
||||
data[i] = AST_LIN2MU((int)val);
|
||||
}
|
||||
|
||||
/* wrap back around from 8000 */
|
||||
|
||||
if (*x >= 8000) *x = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a single tone burst for a specifed duration and frequency.
|
||||
* Returns 0 if successful
|
||||
*/
|
||||
|
||||
static int send_tone_burst(struct ast_channel *chan, float freq, int duration, int tldn)
|
||||
{
|
||||
int res = 0;
|
||||
int i = 0;
|
||||
int x = 0;
|
||||
struct ast_frame *f, wf;
|
||||
|
||||
struct {
|
||||
unsigned char offset[AST_FRIENDLY_OFFSET];
|
||||
unsigned char buf[640];
|
||||
} tone_block;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
|
||||
if (ast_waitfor(chan, -1) < 0){
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
f = ast_read(chan);
|
||||
if (!f){
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
wf.frametype = AST_FRAME_VOICE;
|
||||
wf.subclass = AST_FORMAT_ULAW;
|
||||
wf.offset = AST_FRIENDLY_OFFSET;
|
||||
wf.mallocd = 0;
|
||||
wf.data = tone_block.buf;
|
||||
wf.datalen = f->datalen;
|
||||
wf.samples = wf.datalen;
|
||||
|
||||
make_tone_burst(tone_block.buf, freq, (float) tldn, wf.datalen, &x);
|
||||
|
||||
i += wf.datalen / 8;
|
||||
if (i > duration) {
|
||||
break;
|
||||
}
|
||||
if (ast_write(chan, &wf)){
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Failed to write frame on %s\n", chan->name);
|
||||
ast_log(LOG_WARNING, "AlarmReceiver Failed to write frame on %s\n",chan->name);
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ast_frfree(f);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the difference in milliseconds between two timeval structs
|
||||
*/
|
||||
|
||||
static int ms_diff(struct timeval *tv1, struct timeval *tv2){
|
||||
|
||||
int ms;
|
||||
|
||||
ms = (tv1->tv_sec - tv2->tv_sec) * 1000;
|
||||
ms += (tv1->tv_usec - tv2->tv_usec) / 1000;
|
||||
|
||||
return(ms);
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive a string of DTMF digits where the length of the digit string is known in advance. Do not give preferential
|
||||
* treatment to any digit value, and allow separate time out values to be specified for the first digit and all subsequent
|
||||
* digits.
|
||||
*
|
||||
* Returns 0 if all digits successfully received.
|
||||
* Returns 1 if a digit time out occurred
|
||||
* Returns -1 if the caller hung up or there was a channel error.
|
||||
*
|
||||
*/
|
||||
|
||||
static int receive_dtmf_digits(struct ast_channel *chan, char *digit_string, int length, int fdto, int sdto)
|
||||
{
|
||||
int res = 0;
|
||||
int i = 0;
|
||||
int r;
|
||||
struct ast_frame *f;
|
||||
struct timeval now, lastdigittime;
|
||||
|
||||
gettimeofday(&lastdigittime,NULL);
|
||||
for(;;){
|
||||
gettimeofday(&now,NULL);
|
||||
|
||||
/* if outa time, leave */
|
||||
if (ms_diff(&now,&lastdigittime) >
|
||||
((i > 0) ? sdto : fdto)){
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: DTMF Digit Timeout on %s\n", chan->name);
|
||||
|
||||
ast_log(LOG_DEBUG,"AlarmReceiver: DTMF timeout on chan %s\n",chan->name);
|
||||
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((r = ast_waitfor(chan, -1) < 0)) {
|
||||
ast_log(LOG_DEBUG, "Waitfor returned %d\n", r);
|
||||
continue;
|
||||
}
|
||||
|
||||
f = ast_read(chan);
|
||||
|
||||
if (f == NULL){
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* If they hung up, leave */
|
||||
if ((f->frametype == AST_FRAME_CONTROL) &&
|
||||
(f->subclass == AST_CONTROL_HANGUP)){
|
||||
ast_frfree(f);
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* if not DTMF, just do it again */
|
||||
if (f->frametype != AST_FRAME_DTMF){
|
||||
ast_frfree(f);
|
||||
continue;
|
||||
}
|
||||
|
||||
digit_string[i++] = f->subclass; /* save digit */
|
||||
|
||||
ast_frfree(f);
|
||||
|
||||
/* If we have all the digits we expect, leave */
|
||||
if(i >= length)
|
||||
break;
|
||||
|
||||
gettimeofday(&lastdigittime,NULL);
|
||||
}
|
||||
|
||||
digit_string[i] = '\0'; /* Nul terminate the end of the digit string */
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the metadata to the log file
|
||||
*/
|
||||
|
||||
static int write_metadata( FILE *logfile, char *signalling_type, struct ast_channel *chan)
|
||||
{
|
||||
int res = 0;
|
||||
time_t t;
|
||||
struct tm now;
|
||||
char *cl,*cn;
|
||||
char workstring[80];
|
||||
char timestamp[80];
|
||||
|
||||
/* Extract the caller ID location */
|
||||
|
||||
strncpy(workstring, chan->callerid, sizeof(workstring) - 1);
|
||||
workstring[sizeof(workstring) - 1] = '\0';
|
||||
|
||||
ast_callerid_parse(workstring, &cn, &cl);
|
||||
if (cl)
|
||||
ast_shrink_phone_number(cl);
|
||||
|
||||
|
||||
/* Get the current time */
|
||||
|
||||
time(&t);
|
||||
ast_localtime(&t, &now, NULL);
|
||||
|
||||
/* Format the time */
|
||||
|
||||
strftime(timestamp, sizeof(timestamp), time_stamp_format, &now);
|
||||
|
||||
|
||||
res = fprintf(logfile, "\n\n[metadata]\n\n");
|
||||
|
||||
if(res >= 0)
|
||||
res = fprintf(logfile, "PROTOCOL=%s\n", signalling_type);
|
||||
|
||||
if(res >= 0)
|
||||
res = fprintf(logfile, "CALLINGFROM=%s\n", (!cl) ? "<unknown>" : cl);
|
||||
|
||||
if(res >- 0)
|
||||
res = fprintf(logfile, "CALLERNAME=%s\n", (!cn) ? "<unknown>" : cn);
|
||||
|
||||
if(res >= 0)
|
||||
res = fprintf(logfile, "TIMESTAMP=%s\n\n", timestamp);
|
||||
|
||||
if(res >= 0)
|
||||
res = fprintf(logfile, "[events]\n\n");
|
||||
|
||||
if(res < 0){
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: can't write metadata\n");
|
||||
|
||||
ast_log(LOG_DEBUG,"AlarmReceiver: can't write metadata\n");
|
||||
}
|
||||
else
|
||||
res = 0;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a single event to the log file
|
||||
*/
|
||||
|
||||
static int write_event( FILE *logfile, event_node_t *event)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
if( fprintf(logfile, "%s\n", event->data) < 0)
|
||||
res = -1;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If we are configured to log events, do so here.
|
||||
*
|
||||
*/
|
||||
|
||||
static int log_events(struct ast_channel *chan, char *signalling_type, event_node_t *event)
|
||||
{
|
||||
|
||||
int res = 0;
|
||||
char workstring[sizeof(event_spool_dir)+sizeof(event_file)] = "";
|
||||
int fd;
|
||||
FILE *logfile;
|
||||
event_node_t *elp = event;
|
||||
|
||||
if(strlen(event_spool_dir)){
|
||||
|
||||
/* Make a template */
|
||||
|
||||
strncpy(workstring, event_spool_dir, sizeof(workstring) - 1);
|
||||
strncat(workstring, event_file, sizeof(workstring) - strlen(workstring) - 1);
|
||||
|
||||
/* Make the temporary file */
|
||||
|
||||
fd = mkstemp(workstring);
|
||||
|
||||
if(fd == -1){
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: can't make temporary file\n");
|
||||
ast_log(LOG_DEBUG,"AlarmReceiver: can't make temporary file\n");
|
||||
res = -1;
|
||||
}
|
||||
|
||||
if(!res){
|
||||
logfile = fdopen(fd, "w");
|
||||
if(logfile){
|
||||
/* Write the file */
|
||||
res = write_metadata(logfile, signalling_type, chan);
|
||||
if(!res)
|
||||
while((!res) && (elp != NULL)){
|
||||
res = write_event(logfile, elp);
|
||||
elp = elp->next;
|
||||
}
|
||||
if(!res){
|
||||
if(fflush(logfile) == EOF)
|
||||
res = -1;
|
||||
if(!res){
|
||||
if(fclose(logfile) == EOF)
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function implements the logic to receive the Ademco contact ID format.
|
||||
*
|
||||
* The function will return 0 when the caller hangs up, else a -1 if there was a problem.
|
||||
*/
|
||||
|
||||
static int receive_ademco_contact_id( struct ast_channel *chan, void *data, int fdto, int sdto, int tldn, event_node_t **ehead)
|
||||
{
|
||||
int i,j;
|
||||
int res = 0;
|
||||
int checksum;
|
||||
char event[17];
|
||||
event_node_t *enew, *elp;
|
||||
int got_some_digits = 0;
|
||||
int events_received = 0;
|
||||
int ack_retries = 0;
|
||||
|
||||
static char digit_map[15] = "0123456789*#ABC";
|
||||
static unsigned char digit_weights[15] = {10,1,2,3,4,5,6,7,8,9,11,12,13,14,15};
|
||||
|
||||
database_increment("calls-received");
|
||||
|
||||
/* Wait for first event */
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Waiting for first event from panel\n");
|
||||
|
||||
while(res >= 0){
|
||||
|
||||
if(got_some_digits == 0){
|
||||
|
||||
/* Send ACK tone sequence */
|
||||
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Sending 1400Hz 100ms burst (ACK)\n");
|
||||
|
||||
|
||||
res = send_tone_burst(chan, 1400.0, 100, tldn);
|
||||
|
||||
if(!res)
|
||||
res = ast_safe_sleep(chan, 100);
|
||||
|
||||
if(!res){
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Sending 2300Hz 100ms burst (ACK)\n");
|
||||
|
||||
res = send_tone_burst(chan, 2300.0, 100, tldn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( res >= 0)
|
||||
res = receive_dtmf_digits(chan, event, sizeof(event) - 1, fdto, sdto);
|
||||
|
||||
if (res < 0){
|
||||
|
||||
if(events_received == 0)
|
||||
/* Hangup with no events received should be logged in the DB */
|
||||
database_increment("no-events-received");
|
||||
else{
|
||||
if(ack_retries){
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: ACK retries during this call: %d\n", ack_retries);
|
||||
|
||||
database_increment("ack-retries");
|
||||
}
|
||||
}
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: App exiting...\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(res != 0){
|
||||
/* Didn't get all of the digits */
|
||||
if(option_verbose >= 2)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Incomplete string: %s, trying again...\n", event);
|
||||
|
||||
if(!got_some_digits){
|
||||
got_some_digits = (strlen(event)) ? 1 : 0;
|
||||
ack_retries++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
got_some_digits = 1;
|
||||
|
||||
if(option_verbose >= 2)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Received Event %s\n", event);
|
||||
ast_log(LOG_DEBUG, "AlarmReceiver: Received event: %s\n", event);
|
||||
|
||||
/* Calculate checksum */
|
||||
|
||||
for(j = 0, checksum = 0; j < 16; j++){
|
||||
for(i = 0 ; i < sizeof(digit_map) ; i++){
|
||||
if(digit_map[i] == event[j])
|
||||
break;
|
||||
}
|
||||
|
||||
if(i == 16)
|
||||
break;
|
||||
|
||||
checksum += digit_weights[i];
|
||||
}
|
||||
|
||||
if(i == 16){
|
||||
if(option_verbose >= 2)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Bad DTMF character %c, trying again\n", event[j]);
|
||||
continue; /* Bad character */
|
||||
}
|
||||
|
||||
/* Checksum is mod(15) of the total */
|
||||
|
||||
checksum = checksum % 15;
|
||||
|
||||
if(checksum){
|
||||
database_increment("checksum-errors");
|
||||
if(option_verbose >= 2){
|
||||
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Nonzero checksum\n");
|
||||
ast_log(LOG_DEBUG, "AlarmReceiver: Nonzero checksum\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the message type for correctness */
|
||||
|
||||
if(strncmp(event + 4, "18", 2)){
|
||||
if(strncmp(event + 4, "98", 2)){
|
||||
database_increment("format-errors");
|
||||
if(option_verbose >= 2)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Wrong message type\n");
|
||||
ast_log(LOG_DEBUG, "AlarmReceiver: Wrong message type\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
events_received++;
|
||||
|
||||
/* Queue the Event */
|
||||
|
||||
if((enew = malloc(sizeof(event_node_t))) == NULL){
|
||||
if(option_verbose >= 1)
|
||||
ast_verbose(VERBOSE_PREFIX_1 "AlarmReceiver: Failed to allocate memory\n");
|
||||
ast_log(LOG_WARNING, "AlarmReceiver Failed to allocate memory\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
memset(enew, 0, sizeof(event_node_t));
|
||||
|
||||
enew->next = NULL;
|
||||
strncpy(enew->data, event, sizeof(enew->data) - 1);
|
||||
|
||||
/*
|
||||
* Insert event onto end of list
|
||||
*/
|
||||
|
||||
if(*ehead == NULL){
|
||||
*ehead = enew;
|
||||
}
|
||||
else{
|
||||
for(elp = *ehead; elp->next != NULL; elp = elp->next)
|
||||
;
|
||||
|
||||
elp->next = enew;
|
||||
}
|
||||
|
||||
if(res > 0)
|
||||
res = 0;
|
||||
|
||||
/* Let the user have the option of logging the single event before sending the kissoff tone */
|
||||
|
||||
if((res == 0) && (log_individual_events))
|
||||
res = log_events(chan, ADEMCO_CONTACT_ID, enew);
|
||||
|
||||
/* Wait 200 msec before sending kissoff */
|
||||
|
||||
if(res == 0)
|
||||
res = ast_safe_sleep(chan, 200);
|
||||
|
||||
/* Send the kissoff tone */
|
||||
|
||||
if(res == 0)
|
||||
res = send_tone_burst(chan, 1400.0, 900, tldn);
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This is the main function called by Asterisk Core whenever the App is invoked in the extension logic.
|
||||
* This function will always return 0.
|
||||
*/
|
||||
|
||||
static int alarmreceiver_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
event_node_t *elp, *efree;
|
||||
char signalling_type[64] = "";
|
||||
|
||||
event_node_t *event_head = NULL;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Set write and read formats to ULAW */
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Setting read and write formats to ULAW\n");
|
||||
|
||||
if (ast_set_write_format(chan,AST_FORMAT_ULAW)){
|
||||
ast_log(LOG_WARNING, "AlarmReceiver: Unable to set write format to Mu-law on %s\n",chan->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ast_set_read_format(chan,AST_FORMAT_ULAW)){
|
||||
ast_log(LOG_WARNING, "AlarmReceiver: Unable to set read format to Mu-law on %s\n",chan->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set default values for this invokation of the application */
|
||||
|
||||
strncpy(signalling_type, ADEMCO_CONTACT_ID, sizeof(signalling_type) - 1);
|
||||
|
||||
|
||||
/* Answer the channel if it is not already */
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Answering channel\n");
|
||||
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
|
||||
res = ast_answer(chan);
|
||||
|
||||
if (res) {
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for the connection to settle post-answer */
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Waiting for connection to stabilize\n");
|
||||
|
||||
res = ast_safe_sleep(chan, 1250);
|
||||
|
||||
/* Attempt to receive the events */
|
||||
|
||||
if(!res){
|
||||
|
||||
/* Determine the protocol to receive in advance */
|
||||
/* Note: Ademco contact is the only one supported at this time */
|
||||
/* Others may be added later */
|
||||
|
||||
if(!strcmp(signalling_type, ADEMCO_CONTACT_ID))
|
||||
receive_ademco_contact_id(chan, data, fdtimeout, sdtimeout, toneloudness, &event_head);
|
||||
else
|
||||
res = -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Events queued by receiver, write them all out here if so configured */
|
||||
|
||||
if((!res) && (log_individual_events == 0)){
|
||||
res = log_events(chan, signalling_type, event_head);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Do we exec a command line at the end?
|
||||
*/
|
||||
|
||||
if((!res) && (strlen(event_app)) && (event_head)){
|
||||
ast_log(LOG_DEBUG,"Alarmreceiver: executing: %s\n", event_app);
|
||||
ast_safe_system(event_app);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free up the data allocated in our linked list
|
||||
*/
|
||||
|
||||
for(elp = event_head; (elp != NULL);){
|
||||
efree = elp;
|
||||
elp = elp->next;
|
||||
free(efree);
|
||||
}
|
||||
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Load the configuration from the configuration file
|
||||
*/
|
||||
|
||||
static int load_config(void)
|
||||
{
|
||||
struct ast_config *cfg;
|
||||
char *p;
|
||||
|
||||
/* Read in the config file */
|
||||
|
||||
cfg = ast_load(ALMRCV_CONFIG);
|
||||
|
||||
if(!cfg){
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: No config file\n");
|
||||
}
|
||||
else{
|
||||
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "eventcmd");
|
||||
|
||||
if(p){
|
||||
strncpy(event_app, p, sizeof(event_app) - 1);
|
||||
event_app[sizeof(event_app) - 1] = '\0';
|
||||
}
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "loudness");
|
||||
if(p){
|
||||
toneloudness = atoi(p);
|
||||
if(toneloudness < 100)
|
||||
toneloudness = 100;
|
||||
if(toneloudness > 8192)
|
||||
toneloudness = 8192;
|
||||
}
|
||||
p = ast_variable_retrieve(cfg, "general", "fdtimeout");
|
||||
if(p){
|
||||
fdtimeout = atoi(p);
|
||||
if(fdtimeout < 1000)
|
||||
fdtimeout = 1000;
|
||||
if(fdtimeout > 10000)
|
||||
fdtimeout = 10000;
|
||||
}
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "sdtimeout");
|
||||
if(p){
|
||||
sdtimeout = atoi(p);
|
||||
if(sdtimeout < 110)
|
||||
sdtimeout = 110;
|
||||
if(sdtimeout > 4000)
|
||||
sdtimeout = 4000;
|
||||
|
||||
}
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "logindividualevents");
|
||||
if(p){
|
||||
log_individual_events = ast_true(p);
|
||||
|
||||
}
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "eventspooldir");
|
||||
|
||||
if(p){
|
||||
strncpy(event_spool_dir, p, sizeof(event_spool_dir) - 1);
|
||||
event_spool_dir[sizeof(event_spool_dir) - 1] = '\0';
|
||||
}
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "timestampformat");
|
||||
|
||||
if(p){
|
||||
strncpy(time_stamp_format, p, sizeof(time_stamp_format) - 1);
|
||||
time_stamp_format[sizeof(time_stamp_format) - 1] = '\0';
|
||||
}
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "db-family");
|
||||
|
||||
if(p){
|
||||
strncpy(db_family, p, sizeof(db_family) - 1);
|
||||
db_family[sizeof(db_family) - 1] = '\0';
|
||||
}
|
||||
ast_destroy(cfg);
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* These functions are required to implement an Asterisk App.
|
||||
*/
|
||||
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
load_config();
|
||||
return ast_register_application(app, alarmreceiver_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -18,14 +18,14 @@
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <asterisk/astdb.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "Authentication Application";
|
||||
|
||||
@@ -41,11 +41,7 @@ static char *descrip =
|
||||
"an optional set of opions may be provided by concatenating any\n"
|
||||
"of the following letters:\n"
|
||||
" a - Set account code to the password that is entered\n"
|
||||
" d - Interpret path as database key, not literal file\n"
|
||||
" r - Remove database key upon successful entry (valid with 'd' only)\n"
|
||||
"\n"
|
||||
"When using a database key, the value associated with the key can be\n"
|
||||
"anything.\n"
|
||||
"Returns 0 if the user enters a valid password within three\n"
|
||||
"tries, or -1 otherwise (or on hangup).\n";
|
||||
|
||||
@@ -62,7 +58,7 @@ static int auth_exec(struct ast_channel *chan, void *data)
|
||||
char passwd[256];
|
||||
char *opts;
|
||||
char *prompt;
|
||||
if (!data || ast_strlen_zero(data)) {
|
||||
if (!data || !strlen(data)) {
|
||||
ast_log(LOG_WARNING, "Authenticate requires an argument(password)\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -89,36 +85,24 @@ static int auth_exec(struct ast_channel *chan, void *data)
|
||||
break;
|
||||
res = 0;
|
||||
if (password[0] == '/') {
|
||||
if (strchr(opts, 'd')) {
|
||||
char tmp[256];
|
||||
/* Compare against a database key */
|
||||
if (!ast_db_get(password + 1, passwd, tmp, sizeof(tmp))) {
|
||||
/* It's a good password */
|
||||
if (strchr(opts, 'r')) {
|
||||
ast_db_del(password + 1, passwd);
|
||||
/* Compare against a file */
|
||||
FILE *f;
|
||||
f = fopen(password, "r");
|
||||
if (f) {
|
||||
char buf[256] = "";
|
||||
while(!feof(f)) {
|
||||
fgets(buf, sizeof(buf), f);
|
||||
if (!feof(f) && strlen(buf)) {
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
if (strlen(buf) && !strcmp(passwd, buf))
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Compare against a file */
|
||||
FILE *f;
|
||||
f = fopen(password, "r");
|
||||
if (f) {
|
||||
char buf[256] = "";
|
||||
while(!feof(f)) {
|
||||
fgets(buf, sizeof(buf), f);
|
||||
if (!feof(f) && !ast_strlen_zero(buf)) {
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
if (!ast_strlen_zero(buf) && !strcmp(passwd, buf))
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
if (!ast_strlen_zero(buf) && !strcmp(passwd, buf))
|
||||
break;
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", password, strerror(errno));
|
||||
}
|
||||
fclose(f);
|
||||
if (strlen(buf) && !strcmp(passwd, buf))
|
||||
break;
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", password, strerror(errno));
|
||||
} else {
|
||||
/* Compare against a fixed password */
|
||||
if (!strcmp(passwd, password))
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Check if channel is available";
|
||||
|
||||
static char *app = "ChanIsAvail";
|
||||
@@ -36,14 +38,12 @@ static char *synopsis = "Check if channel is available";
|
||||
static char *descrip =
|
||||
" ChanIsAvail(Technology/resource[&Technology2/resource2...]): \n"
|
||||
"Checks is any of the requested channels are available. If none\n"
|
||||
"of the requested channels are available the new priority will be\n"
|
||||
"n+101 (unless such a priority does not exist or on error, in which\n"
|
||||
"case ChanIsAvail will return -1).\n"
|
||||
"If any of the requested channels are available, the next priority will be n+1,\n"
|
||||
"the channel variable ${AVAILCHAN} will be set to the name of the available channel\n"
|
||||
"and the ChanIsAvail app will return 0.\n"
|
||||
"${AVAILORIGCHAN} is the canonical channel name that was used to create the channel.\n"
|
||||
"${AVAILSTATUS} is the status code for the channel.\n";
|
||||
"of the requested channels are available the new priority will\n"
|
||||
"be n+101 (unless such a priority does not exist, in which case\n"
|
||||
"ChanIsAvail will return -1. If any of the requested channels\n"
|
||||
"are available, the next priority will be n+1, the channel variable\n"
|
||||
"${AVAILCHAN} will be set to the name of the available channel and\n"
|
||||
"the ChanIsAvail app will return 0.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -53,7 +53,7 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=-1;
|
||||
struct localuser *u;
|
||||
char info[512], tmp[512], *peers, *tech, *number, *rest, *cur;
|
||||
char info[256], *peers, *tech, *number, *rest, *cur;
|
||||
struct ast_channel *tempchan;
|
||||
|
||||
if (!data) {
|
||||
@@ -62,7 +62,7 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
strncpy(info, (char *)data, sizeof(info)-1);
|
||||
strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1);
|
||||
peers = info;
|
||||
if (peers) {
|
||||
cur = peers;
|
||||
@@ -76,16 +76,13 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
|
||||
tech = cur;
|
||||
number = strchr(tech, '/');
|
||||
if (!number) {
|
||||
ast_log(LOG_WARNING, "ChanIsAvail argument takes format ([technology]/[device])\n");
|
||||
return -1;
|
||||
ast_log(LOG_WARNING, "ChanIsAvail argument takes format (Zap/[device])\n");
|
||||
continue;
|
||||
}
|
||||
*number = '\0';
|
||||
number++;
|
||||
if ((tempchan = ast_request(tech, chan->nativeformats, number))) {
|
||||
pbx_builtin_setvar_helper(chan, "AVAILCHAN", tempchan->name);
|
||||
/* Store the originally used channel too */
|
||||
snprintf(tmp, sizeof(tmp), "%s/%s", tech, number);
|
||||
pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", tmp);
|
||||
ast_hangup(tempchan);
|
||||
tempchan = NULL;
|
||||
res = 1;
|
||||
@@ -97,7 +94,6 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
if (res < 1) {
|
||||
pbx_builtin_setvar_helper(chan, "AVAILCHAN", "");
|
||||
pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", "");
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority+=100;
|
||||
else
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Trivial application to control playback a sound file
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static char *tdesc = "Control Playback Application";
|
||||
|
||||
static char *app = "ControlPlayback";
|
||||
|
||||
static char *synopsis = "Play a file with fast forward and rewind";
|
||||
|
||||
static char *descrip =
|
||||
"ControlPlayback(filename[|skipms[|ffchar[|rewchar[|stopchar[|pausechr]]]]]):\n"
|
||||
" Plays back a given filename (do not put extension). Options may also\n"
|
||||
" be included following a pipe symbol. You can use * and # to rewind and\n"
|
||||
" fast forward the playback specified. If 'stopchar' is added the file will\n"
|
||||
" terminate playback when 'stopchar' is pressed. Returns -1 if the channel\n"
|
||||
" was hung up, or if the file does not exist. Returns 0 otherwise.\n\n"
|
||||
" Example: exten => 1234,1,ControlPlayback(file|4000|*|#|1|0)\n\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int is_on_phonepad(char key)
|
||||
{
|
||||
return (key == 35 || key == 42 || (key >= 48 && key <= 57)) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int controlplayback_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
int skipms = 0;
|
||||
struct localuser *u;
|
||||
char tmp[256];
|
||||
char *skip = NULL, *fwd = NULL, *rev = NULL, *stop = NULL, *pause = NULL, *file = NULL;
|
||||
|
||||
if (!data || ast_strlen_zero((char *)data)) {
|
||||
ast_log(LOG_WARNING, "ControlPlayback requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(tmp, (char *)data, sizeof(tmp)-1);
|
||||
file = tmp;
|
||||
|
||||
if ((skip=strchr(tmp,'|'))) {
|
||||
*skip = '\0';
|
||||
*skip++;
|
||||
fwd=strchr(skip,'|');
|
||||
if (fwd) {
|
||||
*fwd = '\0';
|
||||
*fwd++;
|
||||
rev = strchr(fwd,'|');
|
||||
if (rev) {
|
||||
*rev = '\0';
|
||||
*rev++;
|
||||
stop = strchr(rev,'|');
|
||||
if (stop) {
|
||||
*stop = '\0';
|
||||
*stop++;
|
||||
pause = strchr(stop,'|');
|
||||
if (pause) {
|
||||
*pause = '\0';
|
||||
*pause++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
skipms = skip ? atoi(skip) : 3000;
|
||||
if (!skipms)
|
||||
skipms = 3000;
|
||||
|
||||
if (!fwd || !is_on_phonepad(*fwd))
|
||||
fwd = "#";
|
||||
if (!rev || !is_on_phonepad(*rev))
|
||||
rev = "*";
|
||||
if (stop && !is_on_phonepad(*stop))
|
||||
stop = NULL;
|
||||
if (pause && !is_on_phonepad(*pause))
|
||||
pause = NULL;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
res = ast_control_streamfile(chan, file, fwd, rev, stop, pause, skipms);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
/* If we stopped on one of our stop keys, return 0 */
|
||||
if(stop && strchr(stop, res))
|
||||
res = 0;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, controlplayback_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* Copyright (c) 2003 Tilghman Lesher. All rights reserved.
|
||||
*
|
||||
* Tilghman Lesher <app_cut__v003@the-tilghman.com>
|
||||
* Tilghman Lesher <app_cut__v002@the-tilghman.com>
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
@@ -82,14 +82,14 @@ static int cut_exec(struct ast_channel *chan, void *data)
|
||||
if (args_okay) {
|
||||
char d, ds[2];
|
||||
char *tmp = alloca(strlen(varname) + 4);
|
||||
char varvalue[MAXRESULT], *tmp2=varvalue;
|
||||
char *tmp2 = alloca(MAXRESULT);
|
||||
char retstring[MAXRESULT];
|
||||
|
||||
memset(retstring, 0, MAXRESULT);
|
||||
|
||||
if (tmp) {
|
||||
if (tmp && tmp2) {
|
||||
snprintf(tmp, strlen(varname) + 4, "${%s}", varname);
|
||||
memset(varvalue, 0, sizeof(varvalue));
|
||||
memset(tmp2, 0, sizeof(tmp2));
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Out of memory");
|
||||
return -1;
|
||||
@@ -101,7 +101,7 @@ static int cut_exec(struct ast_channel *chan, void *data)
|
||||
d = '-';
|
||||
|
||||
/* String form of the delimiter, for use with strsep(3) */
|
||||
snprintf(ds, sizeof(ds), "%c", d);
|
||||
sprintf(ds,"%c",d);
|
||||
|
||||
pbx_substitute_variables_helper(chan, tmp, tmp2, MAXRESULT - 1);
|
||||
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "Date and Time";
|
||||
|
||||
static char *app = "DateTime";
|
||||
|
||||
383
apps/app_db.c
383
apps/app_db.c
@@ -20,31 +20,33 @@
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/astdb.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "Database access functions for Asterisk extension logic";
|
||||
|
||||
static char *g_descrip =
|
||||
" DBget(varname=family/key): Retrieves a value from the Asterisk\n"
|
||||
"database and stores it in the given variable. Always returns 0. If the\n"
|
||||
"requested key is not found, jumps to priority n+101 if available.\n";
|
||||
" DBget(varname=family/key): Retrieves a value from the Asterisk\n"
|
||||
"database and stores it in the given variable. Always returns 0. If the\n"
|
||||
"requested key is not found, jumps to priority n+101 if available.\n";
|
||||
|
||||
static char *p_descrip =
|
||||
" DBput(family/key=value): Stores the given value in the Asterisk\n"
|
||||
"database. Always returns 0.\n";
|
||||
" DBput(family/key=value): Stores the given value in the Asterisk\n"
|
||||
"database. Always returns 0.\n";
|
||||
|
||||
static char *d_descrip =
|
||||
" DBdel(family/key): Deletes a key from the Asterisk database. Always\n"
|
||||
"returns 0.\n";
|
||||
" DBdel(family/key): Deletes a key from the Asterisk database. Always\n"
|
||||
"returns 0.\n";
|
||||
|
||||
static char *dt_descrip =
|
||||
" DBdeltree(family[/keytree]): Deletes a family or keytree from the Asterisk\n"
|
||||
"database. Always returns 0.\n";
|
||||
" DBdeltree(family[/keytree]): Deletes a family or keytree from the Asterisk\n"
|
||||
"database. Always returns 0.\n";
|
||||
|
||||
static char *g_app = "DBget";
|
||||
static char *p_app = "DBput";
|
||||
@@ -60,196 +62,255 @@ STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int deltree_exec (struct ast_channel *chan, void *data)
|
||||
|
||||
static int
|
||||
deltree_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
int arglen;
|
||||
char *argv, *family, *keytree;
|
||||
int arglen;
|
||||
char *argv, *family, *keytree;
|
||||
|
||||
arglen = strlen (data);
|
||||
argv = alloca (arglen + 1);
|
||||
if (!argv) { /* Why would this fail? */
|
||||
ast_log (LOG_DEBUG, "Memory allocation failed\n");
|
||||
return 0;
|
||||
arglen = strlen (data);
|
||||
argv = alloca (arglen + 1);
|
||||
if (!argv) /* Why would this fail? */
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Memory allocation failed\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy (argv, data, arglen + 1);
|
||||
|
||||
if (strchr (argv, '/')) {
|
||||
{
|
||||
family = strsep (&argv, "/");
|
||||
keytree = strsep (&argv, "\0");
|
||||
if (!family || !keytree)
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy (argv, data, arglen + 1);
|
||||
if (!strlen (keytree))
|
||||
keytree = 0;
|
||||
}
|
||||
} else
|
||||
{
|
||||
family = argv;
|
||||
keytree = 0;
|
||||
}
|
||||
|
||||
if (strchr (argv, '/')) {
|
||||
family = strsep (&argv, "/");
|
||||
keytree = strsep (&argv, "\0");
|
||||
if (!family || !keytree) {
|
||||
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
return 0;
|
||||
}
|
||||
if (!strlen (keytree))
|
||||
keytree = 0;
|
||||
} else {
|
||||
family = argv;
|
||||
keytree = 0;
|
||||
}
|
||||
if (option_verbose > 2)
|
||||
{
|
||||
if (keytree)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBdeltree: family=%s, keytree=%s\n",
|
||||
family, keytree);
|
||||
else
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBdeltree: family=%s\n", family);
|
||||
}
|
||||
|
||||
if (option_verbose > 2) {
|
||||
if (keytree)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBdeltree: family=%s, keytree=%s\n", family, keytree);
|
||||
else
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBdeltree: family=%s\n", family);
|
||||
}
|
||||
if (ast_db_deltree (family, keytree))
|
||||
{
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3
|
||||
"DBdeltree: Error deleting key from database.\n");
|
||||
}
|
||||
|
||||
if (ast_db_deltree (family, keytree)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBdeltree: Error deleting key from database.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int del_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
int arglen;
|
||||
char *argv, *family, *key;
|
||||
|
||||
arglen = strlen (data);
|
||||
argv = alloca (arglen + 1);
|
||||
if (!argv) { /* Why would this fail? */
|
||||
ast_log (LOG_DEBUG, "Memory allocation failed\n");
|
||||
return 0;
|
||||
static int
|
||||
del_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
int arglen;
|
||||
char *argv, *family, *key;
|
||||
|
||||
arglen = strlen (data);
|
||||
argv = alloca (arglen + 1);
|
||||
if (!argv) /* Why would this fail? */
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Memory allocation failed\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy (argv, data, arglen + 1);
|
||||
|
||||
if (strchr (argv, '/'))
|
||||
{
|
||||
family = strsep (&argv, "/");
|
||||
key = strsep (&argv, "\0");
|
||||
if (!family || !key)
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy (argv, data, arglen + 1);
|
||||
|
||||
if (strchr (argv, '/')) {
|
||||
family = strsep (&argv, "/");
|
||||
key = strsep (&argv, "\0");
|
||||
if (!family || !key) {
|
||||
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
return 0;
|
||||
}
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBdel: family=%s, key=%s\n", family, key);
|
||||
if (ast_db_del (family, key)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBdel: Error deleting key from database.\n");
|
||||
}
|
||||
} else {
|
||||
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3
|
||||
"DBdel: family=%s, key=%s\n", family, key);
|
||||
if (ast_db_del (family, key))
|
||||
{
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3
|
||||
"DBdel: Error deleting key from database.\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_exec (struct ast_channel *chan, void *data)
|
||||
static int
|
||||
put_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
int arglen;
|
||||
char *argv, *value, *family, *key;
|
||||
int arglen;
|
||||
char *argv, *value, *family, *key;
|
||||
|
||||
arglen = strlen (data);
|
||||
argv = alloca (arglen + 1);
|
||||
if (!argv) { /* Why would this fail? */
|
||||
ast_log (LOG_DEBUG, "Memory allocation failed\n");
|
||||
return 0;
|
||||
arglen = strlen (data);
|
||||
argv = alloca (arglen + 1);
|
||||
if (!argv) /* Why would this fail? */
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Memory allocation failed\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy (argv, data, arglen + 1);
|
||||
|
||||
if (strchr (argv, '/') && strchr (argv, '='))
|
||||
{
|
||||
family = strsep (&argv, "/");
|
||||
key = strsep (&argv, "=");
|
||||
value = strsep (&argv, "\0");
|
||||
if (!value || !family || !key)
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy (argv, data, arglen + 1);
|
||||
|
||||
if (strchr (argv, '/') && strchr (argv, '=')) {
|
||||
family = strsep (&argv, "/");
|
||||
key = strsep (&argv, "=");
|
||||
value = strsep (&argv, "\0");
|
||||
if (!value || !family || !key) {
|
||||
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
return 0;
|
||||
}
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBput: family=%s, key=%s, value=%s\n", family, key, value);
|
||||
if (ast_db_put (family, key, value)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBput: Error writing value to database.\n");
|
||||
}
|
||||
|
||||
} else {
|
||||
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3
|
||||
"DBput: family=%s, key=%s, value=%s\n", family, key,
|
||||
value);
|
||||
if (ast_db_put (family, key, value))
|
||||
{
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3
|
||||
"DBput: Error writing value to database.\n");
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_exec (struct ast_channel *chan, void *data)
|
||||
static int
|
||||
get_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
int arglen;
|
||||
char *argv, *varname, *family, *key;
|
||||
char dbresult[256];
|
||||
int arglen;
|
||||
char *argv, *varname, *family, *key;
|
||||
char dbresult[256];
|
||||
|
||||
arglen = strlen (data);
|
||||
argv = alloca (arglen + 1);
|
||||
if (!argv) { /* Why would this fail? */
|
||||
ast_log (LOG_DEBUG, "Memory allocation failed\n");
|
||||
return 0;
|
||||
arglen = strlen (data);
|
||||
argv = alloca (arglen + 1);
|
||||
if (!argv) /* Why would this fail? */
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Memory allocation failed\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy (argv, data, arglen + 1);
|
||||
|
||||
if (strchr (argv, '=') && strchr (argv, '/'))
|
||||
{
|
||||
varname = strsep (&argv, "=");
|
||||
family = strsep (&argv, "/");
|
||||
key = strsep (&argv, "\0");
|
||||
if (!varname || !family || !key)
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy (argv, data, arglen + 1);
|
||||
|
||||
if (strchr (argv, '=') && strchr (argv, '/')) {
|
||||
varname = strsep (&argv, "=");
|
||||
family = strsep (&argv, "/");
|
||||
key = strsep (&argv, "\0");
|
||||
if (!varname || !family || !key) {
|
||||
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
return 0;
|
||||
}
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBget: varname=%s, family=%s, key=%s\n", varname, family, key);
|
||||
if (!ast_db_get (family, key, dbresult, sizeof (dbresult) - 1)) {
|
||||
pbx_builtin_setvar_helper (chan, varname, dbresult);
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBget: set variable %s to %s\n", varname, dbresult);
|
||||
} else {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBget: Value not found in database.\n");
|
||||
/* Send the call to n+101 priority, where n is the current priority */
|
||||
if (ast_exists_extension (chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
}
|
||||
|
||||
} else {
|
||||
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3
|
||||
"DBget: varname=%s, family=%s, key=%s\n", varname,
|
||||
family, key);
|
||||
if (!ast_db_get (family, key, dbresult, sizeof (dbresult) - 1))
|
||||
{
|
||||
pbx_builtin_setvar_helper (chan, varname, dbresult);
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3
|
||||
"DBget: set variable %s to %s\n", varname, dbresult);
|
||||
}
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3
|
||||
"DBget: Value not found in database.\n");
|
||||
/* Send the call to n+101 priority, where n is the current priority */
|
||||
if (ast_exists_extension
|
||||
(chan, chan->context, chan->exten, chan->priority + 101,
|
||||
chan->callerid))
|
||||
chan->priority += 100;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unload_module (void)
|
||||
int
|
||||
unload_module (void)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
retval = ast_unregister_application (dt_app);
|
||||
retval |= ast_unregister_application (d_app);
|
||||
retval |= ast_unregister_application (p_app);
|
||||
retval |= ast_unregister_application (g_app);
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
retval = ast_unregister_application (dt_app);
|
||||
retval |= ast_unregister_application (d_app);
|
||||
retval |= ast_unregister_application (p_app);
|
||||
retval |= ast_unregister_application (g_app);
|
||||
|
||||
return retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
int load_module (void)
|
||||
int
|
||||
load_module (void)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
retval = ast_register_application (g_app, get_exec, g_synopsis, g_descrip);
|
||||
if (!retval)
|
||||
retval = ast_register_application (p_app, put_exec, p_synopsis, p_descrip);
|
||||
if (!retval)
|
||||
retval = ast_register_application (d_app, del_exec, d_synopsis, d_descrip);
|
||||
if (!retval)
|
||||
retval = ast_register_application (dt_app, deltree_exec, dt_synopsis, dt_descrip);
|
||||
return retval;
|
||||
retval = ast_register_application (g_app, get_exec, g_synopsis, g_descrip);
|
||||
if (!retval)
|
||||
retval =
|
||||
ast_register_application (p_app, put_exec, p_synopsis, p_descrip);
|
||||
if (!retval)
|
||||
retval =
|
||||
ast_register_application (d_app, del_exec, d_synopsis, d_descrip);
|
||||
if (!retval)
|
||||
retval =
|
||||
ast_register_application (dt_app, deltree_exec, dt_synopsis,
|
||||
dt_descrip);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
char *description (void)
|
||||
char *
|
||||
description (void)
|
||||
{
|
||||
return tdesc;
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount (void)
|
||||
int
|
||||
usecount (void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT (res);
|
||||
return res;
|
||||
int res;
|
||||
STANDARD_USECOUNT (res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key ()
|
||||
char *
|
||||
key ()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
663
apps/app_dial.c
663
apps/app_dial.c
@@ -3,9 +3,9 @@
|
||||
*
|
||||
* Trivial application to dial a channel and send an URL on answer
|
||||
*
|
||||
* Copyright (C) 1999-2004, Digium, Inc.
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
@@ -20,12 +20,9 @@
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/say.h>
|
||||
#include <asterisk/config.h>
|
||||
#include <asterisk/features.h>
|
||||
#include <asterisk/parking.h>
|
||||
#include <asterisk/musiconhold.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
@@ -36,6 +33,8 @@
|
||||
#include <sys/signal.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Dialing Application";
|
||||
|
||||
static char *app = "Dial";
|
||||
@@ -50,54 +49,28 @@ static char *descrip =
|
||||
"which first answered. All other calls placed by the Dial app will be hung up\n"
|
||||
"If a timeout is not specified, the Dial application will wait indefinitely\n"
|
||||
"until either one of the called channels answers, the user hangs up, or all\n"
|
||||
"channels return busy or error. In general, the dialer will return 0 if it\n"
|
||||
"channels return busy or error. In general, the dialler will return 0 if it\n"
|
||||
"was unable to place the call, or the timeout expired. However, if all\n"
|
||||
"channels were busy, and there exists an extension with priority n+101 (where\n"
|
||||
"n is the priority of the dialer instance), then it will be the next\n"
|
||||
"n is the priority of the dialler instance), then it will be the next\n"
|
||||
"executed extension (this allows you to setup different behavior on busy from\n"
|
||||
"no-answer).\n"
|
||||
" This application returns -1 if the originating channel hangs up, or if the\n"
|
||||
"call is bridged and either of the parties in the bridge terminate the call.\n"
|
||||
"The option string may contain zero or more of the following characters:\n"
|
||||
" 't' -- allow the called user transfer the calling user by hitting #.\n"
|
||||
" 'T' -- allow the calling user to transfer the call by hitting #.\n"
|
||||
" 'f' -- Forces callerid to be set as the extension of the line \n"
|
||||
" making/redirecting the outgoing call. For example, some PSTNs\n"
|
||||
" don't allow callerids from other extensions then the ones\n"
|
||||
" that are assigned to you.\n"
|
||||
" 't' -- allow the called user transfer the calling user\n"
|
||||
" 'T' -- to allow the calling user to transfer the call.\n"
|
||||
" 'r' -- indicate ringing to the calling party, pass no audio until answered.\n"
|
||||
" 'm' -- provide hold music to the calling party until answered.\n"
|
||||
" 'M(x) -- Executes the macro (x) upon connect of the call\n"
|
||||
" 'h' -- allow callee to hang up by hitting *.\n"
|
||||
" 'H' -- allow caller to hang up by hitting *.\n"
|
||||
" 'C' -- reset call detail record for this call.\n"
|
||||
" 'P[(x)]' -- privacy mode, using 'x' as database if provided.\n"
|
||||
" 'g' -- goes on in context if the destination channel hangs up\n"
|
||||
" 'A(x)' -- play an announcement to the called party, using x as file\n"
|
||||
" 'S(x)' -- hangup the call after x seconds AFTER called party picked up\n"
|
||||
" 'D([digits])' -- Send DTMF digit string *after* called party has answered\n"
|
||||
" but before the bridge. (w=500ms sec pause)\n"
|
||||
" 'L(x[:y][:z])' -- Limit the call to 'x' ms warning when 'y' ms are left\n"
|
||||
" repeated every 'z' ms) Only 'x' is required, 'y' and 'z' are optional.\n"
|
||||
" The following special variables are optional:\n"
|
||||
" * LIMIT_PLAYAUDIO_CALLER yes|no (default yes)\n"
|
||||
" Play sounds to the caller.\n"
|
||||
" * LIMIT_PLAYAUDIO_CALLEE yes|no\n"
|
||||
" Play sounds to the callee.\n"
|
||||
" * LIMIT_TIMEOUT_FILE File to play when time is up.\n"
|
||||
" * LIMIT_CONNECT_FILE File to play when call begins.\n"
|
||||
" * LIMIT_WARNING_FILE File to play as warning if 'y' is defined.\n"
|
||||
" 'timeleft' is a special sound macro to auto-say the time \n"
|
||||
" left and is the default.\n\n"
|
||||
" In addition to transferring the call, a call may be parked and then picked\n"
|
||||
"up by another user.\n"
|
||||
" The optional URL will be sent to the called party if the channel supports it.\n"
|
||||
" This application sets the following channel variables upon completion:\n"
|
||||
" DIALEDTIME Time from dial to answer\n"
|
||||
" ANSWEREDTIME Time for actual call\n"
|
||||
" DIALSTATUS The status of the call as a text string, one of\n"
|
||||
" CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL\n"
|
||||
"";
|
||||
" The optionnal URL will be sent to the called party if the channel supports\n"
|
||||
"it.\n";
|
||||
|
||||
/* We define a customer "local user" structure because we
|
||||
use it not only for keeping track of what is in use but
|
||||
@@ -110,9 +83,7 @@ struct localuser {
|
||||
int allowredirect_out;
|
||||
int ringbackonly;
|
||||
int musiconhold;
|
||||
int allowdisconnect_in;
|
||||
int allowdisconnect_out;
|
||||
int forcecallerid;
|
||||
int allowdisconnect;
|
||||
struct localuser *next;
|
||||
};
|
||||
|
||||
@@ -132,33 +103,43 @@ static void hanguptree(struct localuser *outgoing, struct ast_channel *exception
|
||||
}
|
||||
}
|
||||
|
||||
#define AST_MAX_WATCHERS 256
|
||||
#define MAX 256
|
||||
|
||||
static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect_in, int *allowdisconnect_out, int *sentringing, char *status, size_t statussize)
|
||||
static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect)
|
||||
{
|
||||
struct localuser *o;
|
||||
int found;
|
||||
int numlines;
|
||||
int numbusy = 0;
|
||||
int numcongestion = 0;
|
||||
int numnochan = 0;
|
||||
int sentringing = 0;
|
||||
int numbusies = 0;
|
||||
int orig = *to;
|
||||
struct ast_frame *f;
|
||||
struct ast_channel *peer = NULL;
|
||||
struct ast_channel *watchers[AST_MAX_WATCHERS];
|
||||
struct ast_channel *watchers[MAX];
|
||||
int pos;
|
||||
int single;
|
||||
int moh=0;
|
||||
int ringind=0;
|
||||
struct ast_channel *winner;
|
||||
|
||||
single = (outgoing && !outgoing->next && !outgoing->musiconhold && !outgoing->ringbackonly);
|
||||
|
||||
if (single) {
|
||||
/* Turn off hold music, etc */
|
||||
ast_deactivate_generator(in);
|
||||
ast_indicate(in, -1);
|
||||
/* If we are calling a single channel, make them compatible for in-band tone purpose */
|
||||
ast_channel_make_compatible(outgoing->chan, in);
|
||||
}
|
||||
|
||||
if (outgoing) {
|
||||
moh = outgoing->musiconhold;
|
||||
ringind = outgoing->ringbackonly;
|
||||
if (outgoing->musiconhold) {
|
||||
ast_moh_start(in, NULL);
|
||||
} else if (outgoing->ringbackonly) {
|
||||
ast_indicate(in, AST_CONTROL_RINGING);
|
||||
}
|
||||
}
|
||||
|
||||
while(*to && !peer) {
|
||||
o = outgoing;
|
||||
@@ -176,15 +157,9 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
numlines++;
|
||||
}
|
||||
if (found < 0) {
|
||||
if (numlines == (numbusy + numcongestion + numnochan)) {
|
||||
if (numlines == numbusies) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time\n");
|
||||
if (numbusy)
|
||||
strncpy(status, "BUSY", statussize - 1);
|
||||
else if (numcongestion)
|
||||
strncpy(status, "CONGESTION", statussize - 1);
|
||||
else if (numnochan)
|
||||
strncpy(status, "CHANUNAVAIL", statussize - 1);
|
||||
ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy at this time\n");
|
||||
/* See if there is a special busy message */
|
||||
if (ast_exists_extension(in, in->context, in->exten, in->priority + 101, in->callerid))
|
||||
in->priority+=100;
|
||||
@@ -193,6 +168,12 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
ast_verbose( VERBOSE_PREFIX_2 "No one is available to answer at this time\n");
|
||||
}
|
||||
*to = 0;
|
||||
/* if no one available we'd better stop MOH/ringing to */
|
||||
if (moh) {
|
||||
ast_moh_stop(in);
|
||||
} else if (ringind) {
|
||||
ast_indicate(in, -1);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
winner = ast_waitfor_n(watchers, pos, to);
|
||||
@@ -205,86 +186,29 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
peer = o->chan;
|
||||
*allowredir_in = o->allowredirect_in;
|
||||
*allowredir_out = o->allowredirect_out;
|
||||
*allowdisconnect_in = o->allowdisconnect_in;
|
||||
*allowdisconnect_out = o->allowdisconnect_out;
|
||||
*allowdisconnect = o->allowdisconnect;
|
||||
}
|
||||
} else if (o->chan && (o->chan == winner)) {
|
||||
if (!ast_strlen_zero(o->chan->call_forward)) {
|
||||
char tmpchan[256]="";
|
||||
char *stuff;
|
||||
char *tech;
|
||||
strncpy(tmpchan, o->chan->call_forward, sizeof(tmpchan) - 1);
|
||||
if ((stuff = strchr(tmpchan, '/'))) {
|
||||
*stuff = '\0';
|
||||
stuff++;
|
||||
tech = tmpchan;
|
||||
} else {
|
||||
snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
|
||||
stuff = tmpchan;
|
||||
tech = "Local";
|
||||
}
|
||||
if (strlen(o->chan->call_forward)) {
|
||||
char tmpchan[256];
|
||||
/* Before processing channel, go ahead and check for forwarding */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s@%s' (thanks to %s)\n", in->name, o->chan->call_forward, o->chan->context, o->chan->name);
|
||||
/* Setup parameters */
|
||||
o->chan = ast_request(tech, in->nativeformats, stuff);
|
||||
snprintf(tmpchan, sizeof(tmpchan),"%s@%s", o->chan->call_forward, o->chan->context);
|
||||
ast_hangup(o->chan);
|
||||
o->chan = ast_request("Local", in->nativeformats, tmpchan);
|
||||
if (!o->chan) {
|
||||
ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
|
||||
ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s'\n", tmpchan);
|
||||
o->stillgoing = 0;
|
||||
numnochan++;
|
||||
} else {
|
||||
if (o->chan->callerid)
|
||||
free(o->chan->callerid);
|
||||
|
||||
o->chan->callerid = NULL;
|
||||
|
||||
if (o->forcecallerid) {
|
||||
char *newcid = NULL;
|
||||
|
||||
if (strlen(in->macroexten))
|
||||
newcid = in->macroexten;
|
||||
else
|
||||
newcid = in->exten;
|
||||
o->chan->callerid = strdup(newcid);
|
||||
strncpy(o->chan->accountcode, winner->accountcode, sizeof(o->chan->accountcode) - 1);
|
||||
o->chan->cdrflags = winner->cdrflags;
|
||||
if (!o->chan->callerid)
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
} else {
|
||||
if (in->callerid) {
|
||||
o->chan->callerid = strdup(in->callerid);
|
||||
if (!o->chan->callerid)
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
}
|
||||
strncpy(o->chan->accountcode, in->accountcode, sizeof(o->chan->accountcode) - 1);
|
||||
o->chan->cdrflags = in->cdrflags;
|
||||
}
|
||||
|
||||
if (in->ani) {
|
||||
if (o->chan->ani)
|
||||
free(o->chan->ani);
|
||||
o->chan->ani = malloc(strlen(in->ani) + 1);
|
||||
if (o->chan->ani)
|
||||
strncpy(o->chan->ani, in->ani, strlen(in->ani));
|
||||
else
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
}
|
||||
if (o->chan->rdnis)
|
||||
free(o->chan->rdnis);
|
||||
if (!ast_strlen_zero(in->macroexten))
|
||||
o->chan->rdnis = strdup(in->macroexten);
|
||||
else
|
||||
o->chan->rdnis = strdup(in->exten);
|
||||
if (ast_call(o->chan, tmpchan, 0)) {
|
||||
ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
|
||||
o->stillgoing = 0;
|
||||
ast_hangup(o->chan);
|
||||
o->chan = NULL;
|
||||
numnochan++;
|
||||
}
|
||||
numbusies++;
|
||||
} else if (ast_call(o->chan, tmpchan, 0)) {
|
||||
ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
|
||||
o->stillgoing = 0;
|
||||
ast_hangup(o->chan);
|
||||
o->chan = NULL;
|
||||
numbusies++;
|
||||
}
|
||||
/* Hangup the original channel now, in case we needed it */
|
||||
ast_hangup(winner);
|
||||
continue;
|
||||
}
|
||||
f = ast_read(winner);
|
||||
@@ -299,8 +223,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
peer = o->chan;
|
||||
*allowredir_in = o->allowredirect_in;
|
||||
*allowredir_out = o->allowredirect_out;
|
||||
*allowdisconnect_in = o->allowdisconnect_in;
|
||||
*allowdisconnect_out = o->allowdisconnect_out;
|
||||
*allowdisconnect = o->allowdisconnect;
|
||||
}
|
||||
break;
|
||||
case AST_CONTROL_BUSY:
|
||||
@@ -312,7 +235,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
o->stillgoing = 0;
|
||||
if (in->cdr)
|
||||
ast_cdr_busy(in->cdr);
|
||||
numbusy++;
|
||||
numbusies++;
|
||||
break;
|
||||
case AST_CONTROL_CONGESTION:
|
||||
if (option_verbose > 2)
|
||||
@@ -323,32 +246,29 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
o->stillgoing = 0;
|
||||
if (in->cdr)
|
||||
ast_cdr_busy(in->cdr);
|
||||
numcongestion++;
|
||||
numbusies++;
|
||||
break;
|
||||
case AST_CONTROL_RINGING:
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
|
||||
if (!(*sentringing) && !outgoing->musiconhold) {
|
||||
if (!sentringing && !moh) {
|
||||
ast_indicate(in, AST_CONTROL_RINGING);
|
||||
(*sentringing)++;
|
||||
sentringing++;
|
||||
ringind++;
|
||||
}
|
||||
break;
|
||||
case AST_CONTROL_PROGRESS:
|
||||
if (option_verbose > 2)
|
||||
ast_verbose ( VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", o->chan->name,in->name);
|
||||
if (!outgoing->ringbackonly)
|
||||
ast_indicate(in, AST_CONTROL_PROGRESS);
|
||||
ast_indicate(in, AST_CONTROL_PROGRESS);
|
||||
break;
|
||||
case AST_CONTROL_OFFHOOK:
|
||||
/* Ignore going off hook */
|
||||
break;
|
||||
case -1:
|
||||
if (!outgoing->ringbackonly && !outgoing->musiconhold) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name);
|
||||
ast_indicate(in, -1);
|
||||
(*sentringing) = 0;
|
||||
}
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name);
|
||||
ast_indicate(in, -1);
|
||||
break;
|
||||
default:
|
||||
ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
|
||||
@@ -383,18 +303,13 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
|
||||
/* Got hung up */
|
||||
*to=-1;
|
||||
strncpy(status, "CANCEL", statussize - 1);
|
||||
if (f)
|
||||
ast_frfree(f);
|
||||
return NULL;
|
||||
}
|
||||
if (f && (f->frametype == AST_FRAME_DTMF) && *allowdisconnect_out &&
|
||||
if (f && (f->frametype == AST_FRAME_DTMF) && *allowdisconnect &&
|
||||
(f->subclass == '*')) {
|
||||
if (option_verbose > 3)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
|
||||
*to=0;
|
||||
strcpy(status, "CANCEL");
|
||||
ast_frfree(f);
|
||||
return NULL;
|
||||
}
|
||||
if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF))) {
|
||||
@@ -406,6 +321,11 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
if (!*to && (option_verbose > 2))
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
|
||||
}
|
||||
if (moh) {
|
||||
ast_moh_stop(in);
|
||||
} else if (ringind) {
|
||||
ast_indicate(in, -1);
|
||||
}
|
||||
|
||||
return peer;
|
||||
|
||||
@@ -415,7 +335,7 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=-1;
|
||||
struct localuser *u;
|
||||
char *info, *peers, *timeout, *tech, *number, *rest, *cur;
|
||||
char info[256], *peers, *timeout, *tech, *number, *rest, *cur;
|
||||
char privdb[256] = "", *s;
|
||||
char announcemsg[256] = "", *ann;
|
||||
struct localuser *outgoing=NULL, *tmp;
|
||||
@@ -423,59 +343,32 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
int to;
|
||||
int allowredir_in=0;
|
||||
int allowredir_out=0;
|
||||
int allowdisconnect_in=0;
|
||||
int allowdisconnect_out=0;
|
||||
int hasmacro = 0;
|
||||
int allowdisconnect=0;
|
||||
int privacy=0;
|
||||
int announce=0;
|
||||
int resetcdr=0;
|
||||
int cnt=0;
|
||||
char numsubst[AST_MAX_EXTENSION];
|
||||
char restofit[AST_MAX_EXTENSION];
|
||||
char *transfer = NULL;
|
||||
char *newnum;
|
||||
char callerid[256] = "", *l, *n;
|
||||
char callerid[256], *l, *n;
|
||||
char *url=NULL; /* JDG */
|
||||
struct ast_var_t *current;
|
||||
struct varshead *headp, *newheadp;
|
||||
struct ast_var_t *newvar;
|
||||
int go_on=0;
|
||||
unsigned int calldurationlimit=0;
|
||||
char *cdl;
|
||||
time_t now;
|
||||
struct ast_bridge_config config;
|
||||
long timelimit = 0;
|
||||
long play_warning = 0;
|
||||
long warning_freq=0;
|
||||
char *warning_sound=NULL;
|
||||
char *end_sound=NULL;
|
||||
char *start_sound=NULL;
|
||||
char *limitptr;
|
||||
char limitdata[256];
|
||||
char *sdtmfptr;
|
||||
char sdtmfdata[256] = "";
|
||||
char *stack,*var;
|
||||
char *mac = NULL, macroname[256] = "";
|
||||
char status[256]="";
|
||||
char toast[80];
|
||||
int play_to_caller=0,play_to_callee=0;
|
||||
int playargs=0, sentringing=0, moh=0;
|
||||
int digit = 0;
|
||||
time_t start_time, answer_time, end_time;
|
||||
|
||||
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout|options)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(info = ast_strdupa(data))) {
|
||||
ast_log(LOG_WARNING, "Unable to dupe data :(\n");
|
||||
ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
strncpy(info, (char *)data, sizeof(info) - 1);
|
||||
peers = info;
|
||||
if (peers) {
|
||||
|
||||
timeout = strchr(info, '|');
|
||||
if (timeout) {
|
||||
*timeout = '\0';
|
||||
@@ -497,150 +390,13 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
} else
|
||||
timeout = NULL;
|
||||
if (!peers || ast_strlen_zero(peers)) {
|
||||
if (!peers || !strlen(peers)) {
|
||||
ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
if (transfer) {
|
||||
|
||||
/* Extract call duration limit */
|
||||
if ((cdl = strstr(transfer, "S("))) {
|
||||
calldurationlimit=atoi(cdl+2);
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %i seconds.\n",calldurationlimit);
|
||||
}
|
||||
|
||||
/* DTMF SCRIPT*/
|
||||
if ((sdtmfptr = strstr(transfer, "D("))) {
|
||||
strncpy(sdtmfdata, sdtmfptr + 2, sizeof(sdtmfdata) - 1);
|
||||
/* Overwrite with X's what was the sdtmf info */
|
||||
while (*sdtmfptr && (*sdtmfptr != ')'))
|
||||
*(sdtmfptr++) = 'X';
|
||||
if (*sdtmfptr)
|
||||
*sdtmfptr = 'X';
|
||||
/* Now find the end */
|
||||
sdtmfptr = strchr(sdtmfdata, ')');
|
||||
if (sdtmfptr)
|
||||
*sdtmfptr = '\0';
|
||||
else
|
||||
ast_log(LOG_WARNING, "D( Data lacking trailing ')'\n");
|
||||
}
|
||||
|
||||
/* XXX LIMIT SUPPORT */
|
||||
if ((limitptr = strstr(transfer, "L("))) {
|
||||
strncpy(limitdata, limitptr + 2, sizeof(limitdata) - 1);
|
||||
/* Overwrite with X's what was the limit info */
|
||||
while(*limitptr && (*limitptr != ')'))
|
||||
*(limitptr++) = 'X';
|
||||
if (*limitptr)
|
||||
*limitptr = 'X';
|
||||
/* Now find the end */
|
||||
limitptr = strchr(limitdata, ')');
|
||||
if (limitptr)
|
||||
*limitptr = '\0';
|
||||
else
|
||||
ast_log(LOG_WARNING, "Limit Data lacking trailing ')'\n");
|
||||
|
||||
var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
|
||||
play_to_caller = var ? ast_true(var) : 1;
|
||||
|
||||
var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
|
||||
play_to_callee = var ? ast_true(var) : 0;
|
||||
|
||||
if (!play_to_caller && !play_to_callee)
|
||||
play_to_caller=1;
|
||||
|
||||
var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
|
||||
warning_sound = var ? var : "timeleft";
|
||||
|
||||
var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
|
||||
end_sound = var ? var : NULL;
|
||||
|
||||
var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
|
||||
start_sound = var ? var : NULL;
|
||||
|
||||
var=stack=limitdata;
|
||||
|
||||
var = strsep(&stack, ":");
|
||||
if (var) {
|
||||
timelimit = atol(var);
|
||||
playargs++;
|
||||
var = strsep(&stack, ":");
|
||||
if (var) {
|
||||
play_warning = atol(var);
|
||||
playargs++;
|
||||
var = strsep(&stack, ":");
|
||||
if(var) {
|
||||
warning_freq = atol(var);
|
||||
playargs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!timelimit) {
|
||||
timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
|
||||
warning_sound=NULL;
|
||||
}
|
||||
/* undo effect of S(x) in case they are both used */
|
||||
calldurationlimit=0;
|
||||
/* more efficient do it like S(x) does since no advanced opts*/
|
||||
if (!play_warning && !start_sound && !end_sound && timelimit) {
|
||||
calldurationlimit=timelimit/1000;
|
||||
timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
|
||||
} else if (option_verbose > 2) {
|
||||
ast_verbose(VERBOSE_PREFIX_3"Limit Data:\n");
|
||||
ast_verbose(VERBOSE_PREFIX_3"timelimit=%ld\n",timelimit);
|
||||
ast_verbose(VERBOSE_PREFIX_3"play_warning=%ld\n",play_warning);
|
||||
ast_verbose(VERBOSE_PREFIX_3"play_to_caller=%s\n",play_to_caller ? "yes" : "no");
|
||||
ast_verbose(VERBOSE_PREFIX_3"play_to_callee=%s\n",play_to_callee ? "yes" : "no");
|
||||
ast_verbose(VERBOSE_PREFIX_3"warning_freq=%ld\n",warning_freq);
|
||||
ast_verbose(VERBOSE_PREFIX_3"start_sound=%s\n",start_sound ? start_sound : "UNDEF");
|
||||
ast_verbose(VERBOSE_PREFIX_3"warning_sound=%s\n",warning_sound ? warning_sound : "UNDEF");
|
||||
ast_verbose(VERBOSE_PREFIX_3"end_sound=%s\n",end_sound ? end_sound : "UNDEF");
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX ANNOUNCE SUPPORT */
|
||||
if ((ann = strstr(transfer, "A("))) {
|
||||
announce = 1;
|
||||
strncpy(announcemsg, ann + 2, sizeof(announcemsg) - 1);
|
||||
/* Overwrite with X's what was the announce info */
|
||||
while(*ann && (*ann != ')'))
|
||||
*(ann++) = 'X';
|
||||
if (*ann)
|
||||
*ann = 'X';
|
||||
/* Now find the end of the privdb */
|
||||
ann = strchr(announcemsg, ')');
|
||||
if (ann)
|
||||
*ann = '\0';
|
||||
else {
|
||||
ast_log(LOG_WARNING, "Transfer with Announce spec lacking trailing ')'\n");
|
||||
announce = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the macroname from the dial option string */
|
||||
if ((mac = strstr(transfer, "M("))) {
|
||||
hasmacro = 1;
|
||||
strncpy(macroname, mac + 2, sizeof(macroname) - 1);
|
||||
while (*mac && (*mac != ')'))
|
||||
*(mac++) = 'X';
|
||||
if (*mac)
|
||||
*mac = 'X';
|
||||
else {
|
||||
ast_log(LOG_WARNING, "Could not find macro to which we should jump.\n");
|
||||
hasmacro = 0;
|
||||
}
|
||||
mac = strchr(macroname, ')');
|
||||
if (mac)
|
||||
*mac = '\0';
|
||||
else {
|
||||
ast_log(LOG_WARNING, "Macro flag set without trailing ')'\n");
|
||||
hasmacro = 0;
|
||||
}
|
||||
}
|
||||
/* Extract privacy info from transfer */
|
||||
if ((s = strstr(transfer, "P("))) {
|
||||
privacy = 1;
|
||||
@@ -655,7 +411,7 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
if (s)
|
||||
*s = '\0';
|
||||
else {
|
||||
ast_log(LOG_WARNING, "Transfer with privacy lacking trailing ')'\n");
|
||||
ast_log(LOG_WARNING, "Transfer with privacy lacking trailing '('\n");
|
||||
privacy = 0;
|
||||
}
|
||||
} else if (strchr(transfer, 'P')) {
|
||||
@@ -664,18 +420,28 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
} else if (strchr(transfer, 'C')) {
|
||||
resetcdr = 1;
|
||||
}
|
||||
/* XXX ANNOUNCE SUPPORT */
|
||||
else if ((ann = strstr(transfer, "A("))) {
|
||||
announce = 1;
|
||||
strncpy(announcemsg, ann + 2, sizeof(announcemsg) - 1);
|
||||
cnt=0;
|
||||
while(announcemsg[cnt] != ')') {
|
||||
cnt++;
|
||||
}
|
||||
announcemsg[cnt]='\0';
|
||||
}
|
||||
}
|
||||
if (resetcdr && chan->cdr)
|
||||
ast_cdr_reset(chan->cdr, 0);
|
||||
if (ast_strlen_zero(privdb) && privacy) {
|
||||
if (!strlen(privdb) && privacy) {
|
||||
/* If privdb is not specified and we are using privacy, copy from extension */
|
||||
strncpy(privdb, chan->exten, sizeof(privdb) - 1);
|
||||
}
|
||||
if (privacy) {
|
||||
if (chan->callerid)
|
||||
strncpy(callerid, chan->callerid, sizeof(callerid) - 1);
|
||||
strncpy(callerid, chan->callerid, sizeof(callerid));
|
||||
else
|
||||
callerid[0] = '\0';
|
||||
strcpy(callerid, "");
|
||||
ast_callerid_parse(callerid, &n, &l);
|
||||
if (l) {
|
||||
ast_shrink_phone_number(l);
|
||||
@@ -720,16 +486,10 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
tmp->musiconhold = 1;
|
||||
else tmp->musiconhold = 0;
|
||||
if (strchr(transfer, 'H'))
|
||||
allowdisconnect_out = tmp->allowdisconnect_out = 1;
|
||||
else allowdisconnect_out = tmp->allowdisconnect_out = 0;
|
||||
if(strchr(transfer, 'h'))
|
||||
allowdisconnect_in = tmp->allowdisconnect_in = 1;
|
||||
else allowdisconnect_in = tmp->allowdisconnect_in = 0;
|
||||
allowdisconnect = tmp->allowdisconnect = 1;
|
||||
else allowdisconnect = tmp->allowdisconnect = 0;
|
||||
if(strchr(transfer, 'g'))
|
||||
go_on=1;
|
||||
if (strchr(transfer, 'f'))
|
||||
tmp->forcecallerid = 1;
|
||||
else tmp->forcecallerid = 0;
|
||||
}
|
||||
strncpy(numsubst, number, sizeof(numsubst)-1);
|
||||
/* If we're dialing by extension, look at the extension to know what to dial */
|
||||
@@ -750,29 +510,15 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
cur = rest;
|
||||
continue;
|
||||
}
|
||||
pbx_builtin_setvar_helper(tmp->chan, "DIALEDPEERNUMBER", numsubst);
|
||||
if (!ast_strlen_zero(tmp->chan->call_forward)) {
|
||||
char tmpchan[256]="";
|
||||
char *stuff;
|
||||
char *tech;
|
||||
strncpy(tmpchan, tmp->chan->call_forward, sizeof(tmpchan) - 1);
|
||||
if ((stuff = strchr(tmpchan, '/'))) {
|
||||
*stuff = '\0';
|
||||
stuff++;
|
||||
tech = tmpchan;
|
||||
} else {
|
||||
snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context);
|
||||
stuff = tmpchan;
|
||||
tech = "Local";
|
||||
}
|
||||
/* Before processing channel, go ahead and check for forwarding */
|
||||
if (strlen(tmp->chan->call_forward)) {
|
||||
char tmpchan[256];
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
|
||||
/* Setup parameters */
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Forwarding call to '%s@%s'\n", tmp->chan->call_forward, tmp->chan->context);
|
||||
snprintf(tmpchan, sizeof(tmpchan),"%s@%s", tmp->chan->call_forward, tmp->chan->context);
|
||||
ast_hangup(tmp->chan);
|
||||
tmp->chan = ast_request(tech, chan->nativeformats, stuff);
|
||||
tmp->chan = ast_request("Local", chan->nativeformats, tmpchan);
|
||||
if (!tmp->chan) {
|
||||
ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
|
||||
ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s'\n", tmpchan);
|
||||
free(tmp);
|
||||
cur = rest;
|
||||
continue;
|
||||
@@ -781,21 +527,36 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
/* If creating a SIP channel, look for a variable called */
|
||||
/* VXML_URL in the calling channel and copy it to the */
|
||||
/* new channel. */
|
||||
|
||||
if (strcasecmp(tech,"SIP")==0)
|
||||
{
|
||||
headp=&chan->varshead;
|
||||
AST_LIST_TRAVERSE(headp,current,entries) {
|
||||
if (strcasecmp(ast_var_name(current),"VXML_URL")==0)
|
||||
{
|
||||
newvar=ast_var_assign(ast_var_name(current),ast_var_value(current));
|
||||
newheadp=&tmp->chan->varshead;
|
||||
AST_LIST_INSERT_HEAD(newheadp,newvar,entries);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Check for ALERT_INFO in the SetVar list. This is for */
|
||||
/* SIP distinctive ring as per the RFC. For Cisco 7960s, */
|
||||
/* SetVar(ALERT_INFO=<x>) where x is an integer value 1-5. */
|
||||
/* However, the RFC says it should be a URL. -km- */
|
||||
headp=&chan->varshead;
|
||||
AST_LIST_TRAVERSE(headp,current,entries) {
|
||||
if (!strcasecmp(ast_var_name(current),"VXML_URL") ||
|
||||
!strcasecmp(ast_var_name(current), "ALERT_INFO") ||
|
||||
!strcasecmp(ast_var_name(current), "OSPTOKEN") ||
|
||||
!strcasecmp(ast_var_name(current), "OSPHANDLE"))
|
||||
{
|
||||
newvar=ast_var_assign(ast_var_name(current),ast_var_value(current));
|
||||
newheadp=&tmp->chan->varshead;
|
||||
AST_LIST_INSERT_HEAD(newheadp,newvar,entries);
|
||||
|
||||
if (strcasecmp(tech,"SIP")==0)
|
||||
{
|
||||
headp=&chan->varshead;
|
||||
AST_LIST_TRAVERSE(headp,current,entries) {
|
||||
/* Search for ALERT_INFO */
|
||||
if (strcasecmp(ast_var_name(current),"ALERT_INFO")==0)
|
||||
{
|
||||
newvar=ast_var_assign(ast_var_name(current),ast_var_value(current));
|
||||
newheadp=&tmp->chan->varshead;
|
||||
AST_LIST_INSERT_HEAD(newheadp,newvar,entries);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -811,10 +572,8 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
else
|
||||
tmp->chan->callerid = NULL;
|
||||
/* Copy language from incoming to outgoing */
|
||||
strncpy(tmp->chan->language, chan->language, sizeof(tmp->chan->language) - 1);
|
||||
strncpy(tmp->chan->accountcode, chan->accountcode, sizeof(tmp->chan->accountcode) - 1);
|
||||
tmp->chan->cdrflags = chan->cdrflags;
|
||||
if (ast_strlen_zero(tmp->chan->musicclass))
|
||||
strcpy(tmp->chan->language, chan->language);
|
||||
if (!strlen(tmp->chan->musicclass))
|
||||
strncpy(tmp->chan->musicclass, chan->musicclass, sizeof(tmp->chan->musicclass) - 1);
|
||||
if (chan->ani)
|
||||
tmp->chan->ani = strdup(chan->ani);
|
||||
@@ -835,7 +594,7 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
if (chan->cdr)
|
||||
ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
|
||||
|
||||
/* check the results of ast_call */
|
||||
/* check the restuls of ast_call */
|
||||
if (res) {
|
||||
/* Again, keep going even if there's an error */
|
||||
if (option_debug)
|
||||
@@ -861,31 +620,11 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
cur = rest;
|
||||
} while(cur);
|
||||
|
||||
if (timeout && !ast_strlen_zero(timeout)) {
|
||||
to = atoi(timeout);
|
||||
if (to > 0)
|
||||
to *= 1000;
|
||||
else
|
||||
ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", timeout);
|
||||
} else
|
||||
if (timeout && strlen(timeout))
|
||||
to = atoi(timeout) * 1000;
|
||||
else
|
||||
to = -1;
|
||||
|
||||
if (outgoing) {
|
||||
/* Our status will at least be NOANSWER */
|
||||
strncpy(status, "NOANSWER", sizeof(status) - 1);
|
||||
if (outgoing->musiconhold) {
|
||||
moh=1;
|
||||
ast_moh_start(chan, NULL);
|
||||
} else if (outgoing->ringbackonly) {
|
||||
ast_indicate(chan, AST_CONTROL_RINGING);
|
||||
sentringing++;
|
||||
}
|
||||
} else
|
||||
strncpy(status, "CHANUNAVAIL", sizeof(status) - 1);
|
||||
|
||||
time(&start_time);
|
||||
peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect_in, &allowdisconnect_out, &sentringing, status, sizeof(status));
|
||||
|
||||
peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect);
|
||||
if (!peer) {
|
||||
if (to)
|
||||
/* Musta gotten hung up */
|
||||
@@ -897,12 +636,6 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
goto out;
|
||||
}
|
||||
if (peer) {
|
||||
time(&answer_time);
|
||||
#ifdef OSP_SUPPORT
|
||||
/* Once call is answered, ditch the OSP Handle */
|
||||
pbx_builtin_setvar_helper(chan, "OSPHANDLE", "");
|
||||
#endif
|
||||
strncpy(status, "ANSWER", sizeof(status) - 1);
|
||||
/* Ah ha! Someone answered within the desired timeframe. Of course after this
|
||||
we will always return with -1 so that it is hung up properly after the
|
||||
conversation. */
|
||||
@@ -913,131 +646,43 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
ast_cdr_setdestchan(chan->cdr, peer->name);
|
||||
if (peer->name)
|
||||
pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
|
||||
|
||||
number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
|
||||
if (!number)
|
||||
number = numsubst;
|
||||
pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
|
||||
if (numsubst)
|
||||
pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", numsubst);
|
||||
/* Make sure channels are compatible */
|
||||
res = ast_channel_make_compatible(chan, peer);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
|
||||
ast_hangup(peer);
|
||||
return -1;
|
||||
}
|
||||
/* JDG: sendurl */
|
||||
if( url && !ast_strlen_zero(url) && ast_channel_supports_html(peer) ) {
|
||||
if( url && strlen(url) && ast_channel_supports_html(peer) ) {
|
||||
ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url);
|
||||
ast_channel_sendurl( peer, url );
|
||||
} /* /JDG */
|
||||
if (announce && announcemsg) {
|
||||
if (announce && announcemsg)
|
||||
{
|
||||
int res2;
|
||||
// Start autoservice on the other chan
|
||||
res = ast_autoservice_start(chan);
|
||||
res2 = ast_autoservice_start(chan);
|
||||
// Now Stream the File
|
||||
if (!res)
|
||||
res = ast_streamfile(peer,announcemsg,peer->language);
|
||||
if (!res) {
|
||||
digit = ast_waitstream(peer, AST_DIGIT_ANY);
|
||||
}
|
||||
if (!res2)
|
||||
res2 = ast_streamfile(peer,announcemsg,peer->language);
|
||||
if (!res2)
|
||||
res2 = ast_waitstream(peer,"");
|
||||
// Ok, done. stop autoservice
|
||||
res = ast_autoservice_stop(chan);
|
||||
if (digit > 0 && !res)
|
||||
res = ast_senddigit(chan, digit);
|
||||
else
|
||||
res = digit;
|
||||
|
||||
} else
|
||||
res = 0;
|
||||
|
||||
if (hasmacro && macroname) {
|
||||
void *app = NULL;
|
||||
|
||||
res = ast_autoservice_start(chan);
|
||||
if (res) {
|
||||
ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
|
||||
res = -1;
|
||||
}
|
||||
|
||||
app = pbx_findapp("Macro");
|
||||
|
||||
if (app && !res) {
|
||||
res = pbx_exec(peer, app, macroname, 1);
|
||||
ast_log(LOG_DEBUG, "Macro exited with status %d\n", res);
|
||||
res = 0;
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Could not find application Macro\n");
|
||||
res = -1;
|
||||
}
|
||||
|
||||
if (ast_autoservice_stop(chan) < 0) {
|
||||
ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
|
||||
res = -1;
|
||||
}
|
||||
res2 = ast_autoservice_stop(chan);
|
||||
}
|
||||
res = ast_bridge_call(chan, peer, allowredir_in, allowredir_out, allowdisconnect);
|
||||
|
||||
if (!res) {
|
||||
if (calldurationlimit > 0) {
|
||||
time(&now);
|
||||
chan->whentohangup = now + calldurationlimit;
|
||||
}
|
||||
if (!ast_strlen_zero(sdtmfdata))
|
||||
res = ast_dtmf_stream(peer,chan,sdtmfdata,250);
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
memset(&config,0,sizeof(struct ast_bridge_config));
|
||||
config.play_to_caller=play_to_caller;
|
||||
config.play_to_callee=play_to_callee;
|
||||
config.allowredirect_in = allowredir_in;
|
||||
config.allowredirect_out = allowredir_out;
|
||||
config.allowdisconnect_in = allowdisconnect_in;
|
||||
config.allowdisconnect_out = allowdisconnect_out;
|
||||
config.timelimit = timelimit;
|
||||
config.play_warning = play_warning;
|
||||
config.warning_freq = warning_freq;
|
||||
config.warning_sound = warning_sound;
|
||||
config.end_sound = end_sound;
|
||||
config.start_sound = start_sound;
|
||||
if (moh) {
|
||||
moh = 0;
|
||||
ast_moh_stop(chan);
|
||||
} else if (sentringing) {
|
||||
sentringing = 0;
|
||||
ast_indicate(chan, -1);
|
||||
}
|
||||
/* Be sure no generators are left on it */
|
||||
ast_deactivate_generator(chan);
|
||||
/* Make sure channels are compatible */
|
||||
res = ast_channel_make_compatible(chan, peer);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
|
||||
ast_hangup(peer);
|
||||
return -1;
|
||||
}
|
||||
res = ast_bridge_call(chan,peer,&config);
|
||||
time(&end_time);
|
||||
snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
|
||||
pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
|
||||
snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
|
||||
pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast);
|
||||
|
||||
} else
|
||||
res = -1;
|
||||
|
||||
if (res != AST_PBX_NO_HANGUP_PEER) {
|
||||
if (!chan->_softhangup)
|
||||
chan->hangupcause = peer->hangupcause;
|
||||
if (res != AST_PBX_NO_HANGUP_PEER)
|
||||
ast_hangup(peer);
|
||||
}
|
||||
}
|
||||
out:
|
||||
if (moh) {
|
||||
moh = 0;
|
||||
ast_moh_stop(chan);
|
||||
} else if (sentringing) {
|
||||
sentringing = 0;
|
||||
ast_indicate(chan, -1);
|
||||
}
|
||||
hanguptree(outgoing, NULL);
|
||||
pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
|
||||
ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
if((go_on>0) && (!chan->_softhangup) && (res != AST_PBX_KEEPALIVE))
|
||||
if((go_on>0) && (!chan->_softhangup))
|
||||
res=0;
|
||||
|
||||
return res;
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/config.h>
|
||||
#include <asterisk/say.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include "../asterisk.h"
|
||||
#include "../astconf.h"
|
||||
@@ -32,15 +32,12 @@ static char *app = "Directory";
|
||||
|
||||
static char *synopsis = "Provide directory of voicemail extensions";
|
||||
static char *descrip =
|
||||
" Directory(vm-context[|dial-context[|options]]): Presents the user with a directory\n"
|
||||
"of extensions from which they may select by name. The list of names \n"
|
||||
"and extensions is discovered from voicemail.conf. The vm-context argument\n"
|
||||
"is required, and specifies the context of voicemail.conf to use. The\n"
|
||||
"dial-context is the context to use for dialing the users, and defaults to\n"
|
||||
"the vm-context if unspecified. The 'f' option causes the directory to match\n"
|
||||
"based on the first name in voicemail.conf instead of the last name.\n"
|
||||
"Returns 0 unless the user hangs up. It also sets up the channel on exit\n"
|
||||
"to enter the extension the user selected.\n";
|
||||
" Directory(context): Presents the user with a directory of extensions from\n"
|
||||
"which they may select by name. The list of names and extensions is\n"
|
||||
"discovered from voicemail.conf. The context argument is required, and\n"
|
||||
"specifies the context in which to interpret the extensions. Returns 0\n"
|
||||
"unless the user hangs up. It also sets up the channel on exit to enter the\n"
|
||||
"extension the user selected.\n";
|
||||
|
||||
/* For simplicity, I'm keeping the format compatible with the voicemail config,
|
||||
but i'm open to suggestions for isolating it */
|
||||
@@ -123,108 +120,18 @@ static char *convert(char *lastname)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* play name of mailbox owner.
|
||||
* returns: -1 for bad or missing extension
|
||||
* '1' for selected entry from directory
|
||||
* '*' for skipped entry from directory
|
||||
*/
|
||||
static int play_mailbox_owner(struct ast_channel *chan, char *context, char *dialcontext, char *ext, char *name) {
|
||||
int res = 0;
|
||||
int loop = 3;
|
||||
char fn[256];
|
||||
char fn2[256];
|
||||
|
||||
/* Check for the VoiceMail2 greeting first */
|
||||
snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/greet",
|
||||
(char *)ast_config_AST_SPOOL_DIR, context, ext);
|
||||
|
||||
/* Otherwise, check for an old-style Voicemail greeting */
|
||||
snprintf(fn2, sizeof(fn2), "%s/vm/%s/greet",
|
||||
(char *)ast_config_AST_SPOOL_DIR, ext);
|
||||
|
||||
if (ast_fileexists(fn, NULL, chan->language) > 0) {
|
||||
res = ast_streamfile(chan, fn, chan->language);
|
||||
if (!res) {
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
}
|
||||
ast_stopstream(chan);
|
||||
} else if (ast_fileexists(fn2, NULL, chan->language) > 0) {
|
||||
res = ast_streamfile(chan, fn2, chan->language);
|
||||
if (!res) {
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
}
|
||||
ast_stopstream(chan);
|
||||
} else {
|
||||
res = ast_say_character_str(chan, !ast_strlen_zero(name) ? name : ext,
|
||||
AST_DIGIT_ANY, chan->language);
|
||||
}
|
||||
|
||||
while (loop) {
|
||||
if (!res) {
|
||||
res = ast_streamfile(chan, "dir-instr", chan->language);
|
||||
}
|
||||
if (!res) {
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
}
|
||||
if (!res) {
|
||||
res = ast_waitfordigit(chan, 3000);
|
||||
}
|
||||
ast_stopstream(chan);
|
||||
|
||||
if (res > -1) {
|
||||
switch (res) {
|
||||
case '1':
|
||||
/* Name selected */
|
||||
loop = 0;
|
||||
if (ast_exists_extension(chan,dialcontext,ext,1,chan->callerid)) {
|
||||
strncpy(chan->exten, ext, sizeof(chan->exten)-1);
|
||||
chan->priority = 0;
|
||||
strncpy(chan->context, dialcontext, sizeof(chan->context)-1);
|
||||
} else {
|
||||
ast_log(LOG_WARNING,
|
||||
"Can't find extension '%s' in context '%s'. "
|
||||
"Did you pass the wrong context to Directory?\n",
|
||||
ext, dialcontext);
|
||||
res = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case '*':
|
||||
/* Skip to next match in list */
|
||||
loop = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Not '1', or '*', so decrement number of tries */
|
||||
res = 0;
|
||||
loop--;
|
||||
break;
|
||||
} /* end switch */
|
||||
} /* end if */
|
||||
else {
|
||||
/* User hungup, so jump out now */
|
||||
loop = 0;
|
||||
}
|
||||
} /* end while */
|
||||
|
||||
return(res);
|
||||
}
|
||||
|
||||
static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *context, char *dialcontext, char digit, int last)
|
||||
static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *context, char digit)
|
||||
{
|
||||
/* Read in the first three digits.. "digit" is the first digit, already read */
|
||||
char ext[NUMDIGITS + 1];
|
||||
char name[80] = "";
|
||||
struct ast_variable *v;
|
||||
int res;
|
||||
int found=0;
|
||||
int lastuserchoice = 0;
|
||||
char *start, *pos, *conv,*stringp=NULL;
|
||||
|
||||
if (!context || ast_strlen_zero(context)) {
|
||||
ast_log(LOG_WARNING,
|
||||
"Directory must be called with an argument "
|
||||
"(context in which to interpret extensions)\n");
|
||||
char fn[256];
|
||||
char fn2[256];
|
||||
if (!context || !strlen(context)) {
|
||||
ast_log(LOG_WARNING, "Directory must be called with an argument (context in which to interpret extensions)\n");
|
||||
return -1;
|
||||
}
|
||||
memset(ext, 0, sizeof(ext));
|
||||
@@ -244,9 +151,8 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *
|
||||
strsep(&stringp, ",");
|
||||
pos = strsep(&stringp, ",");
|
||||
if (pos) {
|
||||
strncpy(name, pos, sizeof(name) - 1);
|
||||
/* Grab the last name */
|
||||
if (last && strrchr(pos,' '))
|
||||
if (strrchr(pos, ' '))
|
||||
pos = strrchr(pos, ' ') + 1;
|
||||
conv = convert(pos);
|
||||
if (conv) {
|
||||
@@ -264,46 +170,59 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *
|
||||
}
|
||||
v = v->next;
|
||||
}
|
||||
|
||||
if (v) {
|
||||
/* We have a match -- play a greeting if they have it */
|
||||
res = play_mailbox_owner(chan, context, dialcontext, v->name, name);
|
||||
switch (res) {
|
||||
case -1:
|
||||
/* user pressed '1' but extension does not exist, or
|
||||
* user hungup
|
||||
*/
|
||||
lastuserchoice = 0;
|
||||
break;
|
||||
case '1':
|
||||
/* user pressed '1' and extensions exists */
|
||||
lastuserchoice = res;
|
||||
strncpy(chan->context, dialcontext, sizeof(chan->context) - 1);
|
||||
strncpy(chan->exten, v->name, sizeof(chan->exten) - 1);
|
||||
/* Check for the VoiceMail2 greeting first */
|
||||
snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/greet", (char *)ast_config_AST_SPOOL_DIR, context, v->name);
|
||||
/* Otherwise, check for an old-style Voicemail greeting */
|
||||
snprintf(fn2, sizeof(fn2), "%s/vm/%s/greet", (char *)ast_config_AST_SPOOL_DIR, v->name);
|
||||
if (ast_fileexists(fn, NULL, chan->language) > 0) {
|
||||
res = ast_streamfile(chan, fn, chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
ast_stopstream(chan);
|
||||
} else if (ast_fileexists(fn2, NULL, chan->language) > 0) {
|
||||
res = ast_streamfile(chan, fn2, chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
ast_stopstream(chan);
|
||||
} else {
|
||||
res = ast_say_digit_str(chan, v->name, AST_DIGIT_ANY, chan->language);
|
||||
}
|
||||
ahem:
|
||||
if (!res)
|
||||
res = ast_streamfile(chan, "dir-instr", chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
if (!res)
|
||||
res = ast_waitfordigit(chan, 3000);
|
||||
ast_stopstream(chan);
|
||||
if (res > -1) {
|
||||
if (res == '1') {
|
||||
strncpy(chan->exten, v->name, sizeof(chan->exten)-1);
|
||||
chan->priority = 0;
|
||||
break;
|
||||
case '*':
|
||||
/* user pressed '*' to skip something found */
|
||||
lastuserchoice = res;
|
||||
strncpy(chan->context, context, sizeof(chan->context)-1);
|
||||
res = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
} else if (res == '*') {
|
||||
res = 0;
|
||||
v = v->next;
|
||||
} else {
|
||||
res = 0;
|
||||
goto ahem;
|
||||
}
|
||||
}
|
||||
v = v->next;
|
||||
} else {
|
||||
if (found)
|
||||
res = ast_streamfile(chan, "dir-nomore", chan->language);
|
||||
else
|
||||
res = ast_streamfile(chan, "dir-nomatch", chan->language);
|
||||
if (!res)
|
||||
res = 1;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastuserchoice != '1') {
|
||||
if (found)
|
||||
res = ast_streamfile(chan, "dir-nomore", chan->language);
|
||||
else
|
||||
res = ast_streamfile(chan, "dir-nomatch", chan->language);
|
||||
if (!res)
|
||||
res = 1;
|
||||
return res;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -313,11 +232,8 @@ static int directory_exec(struct ast_channel *chan, void *data)
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
struct ast_config *cfg;
|
||||
int last = 1;
|
||||
char *context, *dialcontext, *dirintro, *options;
|
||||
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "directory requires an argument (context[,dialcontext])\n");
|
||||
ast_log(LOG_WARNING, "directory requires an argument (context)\n");
|
||||
return -1;
|
||||
}
|
||||
cfg = ast_load(DIRECTORY_CONFIG);
|
||||
@@ -327,40 +243,17 @@ static int directory_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
top:
|
||||
context = ast_strdupa(data);
|
||||
dialcontext = strchr(context, '|');
|
||||
if (dialcontext) {
|
||||
*dialcontext = '\0';
|
||||
dialcontext++;
|
||||
options = strchr(dialcontext, '|');
|
||||
if (options) {
|
||||
*options = '\0';
|
||||
options++;
|
||||
if (strchr(options, 'f'))
|
||||
last = 0;
|
||||
}
|
||||
} else
|
||||
dialcontext = context;
|
||||
dirintro = ast_variable_retrieve(cfg, context, "directoryintro");
|
||||
if (!dirintro || ast_strlen_zero(dirintro))
|
||||
dirintro = ast_variable_retrieve(cfg, "general", "directoryintro");
|
||||
if (!dirintro || ast_strlen_zero(dirintro)) {
|
||||
if (last)
|
||||
dirintro = "dir-intro";
|
||||
else
|
||||
dirintro = "dir-intro-fn";
|
||||
}
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
res = ast_answer(chan);
|
||||
if (!res)
|
||||
res = ast_streamfile(chan, dirintro, chan->language);
|
||||
res = ast_streamfile(chan, "dir-intro", chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
ast_stopstream(chan);
|
||||
if (!res)
|
||||
res = ast_waitfordigit(chan, 5000);
|
||||
if (res > 0) {
|
||||
res = do_directory(chan, cfg, context, dialcontext, res, last);
|
||||
res = do_directory(chan, cfg, (char *)data, res);
|
||||
if (res > 0) {
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
ast_stopstream(chan);
|
||||
|
||||
138
apps/app_disa.c
138
apps/app_disa.c
@@ -17,7 +17,6 @@
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/indications.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
@@ -26,8 +25,12 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
/*
|
||||
#define TONE_BLOCK_SIZE 320
|
||||
*/
|
||||
|
||||
static char *tdesc = "DISA (Direct Inward System Access) Application";
|
||||
|
||||
@@ -80,9 +83,27 @@ STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static float loudness=4096.0;
|
||||
|
||||
static int firstdigittimeout = 20000; /* 20 seconds first digit timeout */
|
||||
static int digittimeout = 10000; /* 10 seconds subsequent digit timeout */
|
||||
|
||||
static void make_tone_block(unsigned char *data, float f1, float f2, int len, int *x)
|
||||
{
|
||||
int i;
|
||||
float val;
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
val = loudness * sin((f1 * 2.0 * M_PI * (*x))/8000.0);
|
||||
val += loudness * sin((f2 * 2.0 * M_PI * (*x)++)/8000.0);
|
||||
data[i] = AST_LIN2MU((int)val);
|
||||
}
|
||||
/* wrap back around from 8000 */
|
||||
if (*x >= 8000) *x = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
static int ms_diff(struct timeval *tv1, struct timeval *tv2)
|
||||
{
|
||||
int ms;
|
||||
@@ -92,26 +113,19 @@ int ms;
|
||||
return(ms);
|
||||
}
|
||||
|
||||
static void play_dialtone(struct ast_channel *chan)
|
||||
{
|
||||
const struct tone_zone_sound *ts = NULL;
|
||||
ts = ast_get_indication_tone(chan->zone, "dial");
|
||||
if (ts)
|
||||
ast_playtones_start(chan, 0, ts->data, 0);
|
||||
else
|
||||
ast_tonepair_start(chan, 350, 440, 0, 0);
|
||||
}
|
||||
|
||||
static int disa_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int i,j,k,x,did_ignore;
|
||||
int i,j,k,x;
|
||||
struct localuser *u;
|
||||
char tmp[256],arg2[256]="",exten[AST_MAX_EXTENSION],acctcode[20]="";
|
||||
char tmp[256],arg2[256],exten[AST_MAX_EXTENSION],acctcode[20];
|
||||
struct {
|
||||
unsigned char offset[AST_FRIENDLY_OFFSET];
|
||||
unsigned char buf[640];
|
||||
} tone_block;
|
||||
char *ourcontext,*ourcallerid;
|
||||
struct ast_frame *f;
|
||||
struct ast_frame *f,wf;
|
||||
struct timeval lastout, now, lastdigittime;
|
||||
int res;
|
||||
time_t rstart;
|
||||
FILE *fp;
|
||||
char *stringp=NULL;
|
||||
|
||||
@@ -136,7 +150,7 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
ourcontext = strsep(&stringp, "|");
|
||||
/* if context specified, save 2nd arg and parse third */
|
||||
if (ourcontext) {
|
||||
strncpy(arg2,ourcontext, sizeof(arg2) - 1);
|
||||
strcpy(arg2,ourcontext);
|
||||
ourcallerid = strsep(&stringp,"|");
|
||||
}
|
||||
/* if context not specified, use "disa" */
|
||||
@@ -152,22 +166,15 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
ast_answer(chan);
|
||||
}
|
||||
i = k = x = 0; /* k is 0 for pswd entry, 1 for ext entry */
|
||||
did_ignore = 0;
|
||||
exten[0] = 0;
|
||||
acctcode[0] = 0;
|
||||
/* can we access DISA without password? */
|
||||
|
||||
ast_log(LOG_DEBUG, "Context: %s\n",ourcontext);
|
||||
|
||||
if (!strcasecmp(tmp, "no-password"))
|
||||
{;
|
||||
k = 1;
|
||||
ast_log(LOG_DEBUG, "DISA no-password login success\n");
|
||||
}
|
||||
gettimeofday(&lastdigittime,NULL);
|
||||
|
||||
play_dialtone(chan);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
gettimeofday(&now,NULL);
|
||||
@@ -198,7 +205,24 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
return -1;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
ast_frfree(f);
|
||||
if (!i || (ast_ignore_pattern(ourcontext, exten) && k)) {
|
||||
wf.frametype = AST_FRAME_VOICE;
|
||||
wf.subclass = AST_FORMAT_ULAW;
|
||||
wf.offset = AST_FRIENDLY_OFFSET;
|
||||
wf.mallocd = 0;
|
||||
wf.data = tone_block.buf;
|
||||
wf.datalen = f->datalen;
|
||||
make_tone_block(tone_block.buf, 350, 440, f->datalen, &x);
|
||||
wf.samples = wf.datalen;
|
||||
ast_frfree(f);
|
||||
if (ast_write(chan, &wf))
|
||||
{
|
||||
ast_log(LOG_WARNING, "DISA Failed to write frame on %s\n",chan->name);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
ast_frfree(f);
|
||||
continue;
|
||||
}
|
||||
/* if not DTMF, just do it again */
|
||||
@@ -210,9 +234,7 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
j = f->subclass; /* save digit */
|
||||
ast_frfree(f);
|
||||
if (i == 0)
|
||||
ast_playtones_stop(chan);
|
||||
|
||||
|
||||
gettimeofday(&lastdigittime,NULL);
|
||||
/* got a DTMF tone */
|
||||
if (i < AST_MAX_EXTENSION) /* if still valid number of digits */
|
||||
@@ -265,52 +287,38 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
}
|
||||
/* password good, set to dial state */
|
||||
ast_log(LOG_DEBUG,"DISA on chan %s password is good\n",chan->name);
|
||||
play_dialtone(chan);
|
||||
|
||||
ast_log(LOG_WARNING,"DISA on chan %s password is good\n",chan->name);
|
||||
k = 1;
|
||||
i = 0; /* re-set buffer pointer */
|
||||
exten[sizeof(acctcode)] = 0;
|
||||
strncpy(acctcode,exten, sizeof(acctcode) - 1);
|
||||
strcpy(acctcode,exten);
|
||||
exten[0] = 0;
|
||||
ast_log(LOG_DEBUG,"Successful DISA log-in on chan %s\n",chan->name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
exten[i++] = j; /* save digit */
|
||||
exten[i] = 0;
|
||||
if (!k) continue; /* if getting password, continue doing it */
|
||||
/* if this exists */
|
||||
|
||||
if (ast_ignore_pattern(ourcontext, exten)) {
|
||||
play_dialtone(chan);
|
||||
did_ignore = 1;
|
||||
} else
|
||||
if (did_ignore) {
|
||||
ast_playtones_stop(chan);
|
||||
did_ignore = 0;
|
||||
}
|
||||
|
||||
/* if can do some more, do it */
|
||||
if (!ast_matchmore_extension(chan,ourcontext,exten,1, chan->callerid)) {
|
||||
if (!ast_matchmore_extension(chan,ourcontext,exten,1, chan->callerid))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (k && ast_exists_extension(chan,ourcontext,exten,1, chan->callerid))
|
||||
{
|
||||
ast_playtones_stop(chan);
|
||||
/* We're authenticated and have a valid extension */
|
||||
if (ourcallerid && *ourcallerid)
|
||||
{
|
||||
if (chan->callerid) free(chan->callerid);
|
||||
chan->callerid = strdup(ourcallerid);
|
||||
}
|
||||
strncpy(chan->exten, exten, sizeof(chan->exten) - 1);
|
||||
strncpy(chan->context, ourcontext, sizeof(chan->context) - 1);
|
||||
strncpy(chan->accountcode, acctcode, sizeof(chan->accountcode) - 1);
|
||||
strcpy(chan->exten,exten);
|
||||
strcpy(chan->context,ourcontext);
|
||||
strcpy(chan->accountcode,acctcode);
|
||||
chan->priority = 0;
|
||||
ast_cdr_init(chan->cdr,chan);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
@@ -318,20 +326,44 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
|
||||
reorder:
|
||||
|
||||
ast_indicate(chan,AST_CONTROL_CONGESTION);
|
||||
/* something is invalid, give em reorder for several seconds */
|
||||
time(&rstart);
|
||||
while(time(NULL) < rstart + 10)
|
||||
|
||||
/* something is invalid, give em reorder forever */
|
||||
x = 0;
|
||||
k = 0; /* k = 0 means busy tone, k = 1 means silence) */
|
||||
i = 0; /* Number of samples we've done */
|
||||
for(;;)
|
||||
{
|
||||
if (ast_waitfor(chan, -1) < 0)
|
||||
break;
|
||||
f = ast_read(chan);
|
||||
if (!f)
|
||||
break;
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
wf.frametype = AST_FRAME_VOICE;
|
||||
wf.subclass = AST_FORMAT_ULAW;
|
||||
wf.offset = AST_FRIENDLY_OFFSET;
|
||||
wf.mallocd = 0;
|
||||
wf.data = tone_block.buf;
|
||||
wf.datalen = f->datalen;
|
||||
wf.samples = wf.datalen;
|
||||
if (k)
|
||||
memset(tone_block.buf, 0x7f, wf.datalen);
|
||||
else
|
||||
make_tone_block(tone_block.buf,480.0, 620.0,wf.datalen, &x);
|
||||
i += wf.datalen / 8;
|
||||
if (i > 250) {
|
||||
i = 0;
|
||||
k = !k;
|
||||
}
|
||||
if (ast_write(chan, &wf))
|
||||
{
|
||||
ast_log(LOG_WARNING, "DISA Failed to write frame on %s\n",chan->name);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
ast_playtones_stop(chan);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "Simple Echo Application";
|
||||
|
||||
static char *app = "Echo";
|
||||
@@ -49,8 +52,6 @@ static int echo_exec(struct ast_channel *chan, void *data)
|
||||
f = ast_read(chan);
|
||||
if (!f)
|
||||
break;
|
||||
f->delivery.tv_sec = 0;
|
||||
f->delivery.tv_usec = 0;
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
if (ast_write(chan, f))
|
||||
break;
|
||||
|
||||
@@ -20,13 +20,15 @@
|
||||
#include <asterisk/config.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/enum.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "ENUM Lookup";
|
||||
|
||||
static char *app = "EnumLookup";
|
||||
@@ -47,7 +49,7 @@ static char *descrip =
|
||||
|
||||
#define ENUM_CONFIG "enum.conf"
|
||||
|
||||
static char h323driver[80] = "";
|
||||
static char h323driver[80];
|
||||
#define H323DRIVERDEFAULT "H323"
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
@@ -62,7 +64,7 @@ static int enumlookup_exec(struct ast_channel *chan, void *data)
|
||||
char tmp[256];
|
||||
char *c,*t;
|
||||
struct localuser *u;
|
||||
if (!data || ast_strlen_zero(data)) {
|
||||
if (!data || !strlen(data)) {
|
||||
ast_log(LOG_WARNING, "EnumLookup requires an argument (extension)\n");
|
||||
res = 1;
|
||||
}
|
||||
@@ -126,7 +128,7 @@ static int enumlookup_exec(struct ast_channel *chan, void *data)
|
||||
else
|
||||
res = 0;
|
||||
}
|
||||
} else if (!ast_strlen_zero(tech)) {
|
||||
} else if (strlen(tech)) {
|
||||
ast_log(LOG_NOTICE, "Don't know how to handle technology '%s'\n", tech);
|
||||
res = 0;
|
||||
}
|
||||
@@ -148,9 +150,9 @@ static int load_config(void)
|
||||
cfg = ast_load(ENUM_CONFIG);
|
||||
if (cfg) {
|
||||
if (!(s=ast_variable_retrieve(cfg, "general", "h323driver"))) {
|
||||
strncpy(h323driver, H323DRIVERDEFAULT, sizeof(h323driver) - 1);
|
||||
strcpy(h323driver, H323DRIVERDEFAULT);
|
||||
} else {
|
||||
strncpy(h323driver, s, sizeof(h323driver) - 1);
|
||||
strcpy(h323driver, s);
|
||||
}
|
||||
ast_destroy(cfg);
|
||||
return 0;
|
||||
|
||||
101
apps/app_eval.c
101
apps/app_eval.c
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Eval application
|
||||
*
|
||||
* Copyright (c) 2004 Tilghman Lesher. All rights reserved.
|
||||
*
|
||||
* Tilghman Lesher <app_eval__v001@the-tilghman.com>
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* This code is released by the author with no restrictions on usage.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
|
||||
/* Maximum length of any variable */
|
||||
#define MAXRESULT 1024
|
||||
|
||||
static char *tdesc = "Reevaluates strings";
|
||||
|
||||
static char *app_eval = "Eval";
|
||||
|
||||
static char *eval_synopsis = "Eval(newvar=somestring)";
|
||||
|
||||
static char *eval_descrip =
|
||||
"Eval(newvar=somestring)\n"
|
||||
" Normally Asterisk evaluates variables inline. But what if you want to\n"
|
||||
"store variable offsets in a database, to be evaluated later? Eval is\n"
|
||||
"the answer, by allowing a string to be evaluated twice in the dialplan,\n"
|
||||
"the first time as part of the normal dialplan, and the second using Eval.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int eval_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *s, *newvar=NULL, tmp[MAXRESULT];
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Check and parse arguments */
|
||||
if (data) {
|
||||
s = ast_strdupa((char *)data);
|
||||
if (s) {
|
||||
newvar = strsep(&s, "=");
|
||||
if (newvar && (newvar[0] != '\0')) {
|
||||
memset(tmp, 0, MAXRESULT);
|
||||
pbx_substitute_variables_helper(chan, s, tmp, MAXRESULT - 1);
|
||||
pbx_builtin_setvar_helper(chan, newvar, tmp);
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app_eval);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app_eval, eval_exec, eval_synopsis, eval_descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
113
apps/app_exec.c
113
apps/app_exec.c
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Exec application
|
||||
*
|
||||
* Copyright (c) 2004 Tilghman Lesher. All rights reserved.
|
||||
*
|
||||
* Tilghman Lesher <app_exec__v001@the-tilghman.com>
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* This code is released by the author with no restrictions on usage.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
|
||||
/* Maximum length of any variable */
|
||||
#define MAXRESULT 1024
|
||||
|
||||
static char *tdesc = "Executes applications";
|
||||
|
||||
static char *app_exec = "Exec";
|
||||
|
||||
static char *exec_synopsis = "Exec(Appname(arguments))";
|
||||
|
||||
static char *exec_descrip =
|
||||
"Exec(appname(arguments))\n"
|
||||
" Allows an arbitrary application to be invoked even when not\n"
|
||||
"hardcoded into the dialplan. Returns whatever value the\n"
|
||||
"app returns or -2 when the app cannot be found.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int exec_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *s, *appname, *endargs, args[MAXRESULT];
|
||||
struct ast_app *app;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
memset(args, 0, MAXRESULT);
|
||||
|
||||
/* Check and parse arguments */
|
||||
if (data) {
|
||||
s = ast_strdupa((char *)data);
|
||||
if (s) {
|
||||
appname = strsep(&s, "(");
|
||||
if (s) {
|
||||
endargs = strrchr(s, ')');
|
||||
if (endargs)
|
||||
*endargs = '\0';
|
||||
pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
|
||||
}
|
||||
if (appname) {
|
||||
app = pbx_findapp(appname);
|
||||
if (app) {
|
||||
res = pbx_exec(chan, app, args, 1);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
|
||||
res = -2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app_exec);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app_exec, exec_exec, exec_synopsis, exec_descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* Copyright (C) 2002, Christos Ricudis
|
||||
*
|
||||
* Christos Ricudis <ricudis@itc.auth.gr>
|
||||
* Christos Ricudis <ricudis@paiko.gr>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
@@ -19,8 +19,6 @@
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/md5.h>
|
||||
#include <asterisk/config.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
@@ -36,6 +34,7 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
#define FESTIVAL_CONFIG "festival.conf"
|
||||
@@ -156,9 +155,6 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Answer if it's not already going */
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
ast_answer(chan);
|
||||
ast_stopstream(chan);
|
||||
|
||||
owriteformat = chan->writeformat;
|
||||
@@ -199,7 +195,7 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
|
||||
needed = f->samples * 2;
|
||||
if (needed > sizeof(myf.frdata)) {
|
||||
ast_log(LOG_WARNING, "Only able to deliver %d of %d requested samples\n",
|
||||
(int)sizeof(myf.frdata) / 2, needed/2);
|
||||
sizeof(myf.frdata) / 2, needed/2);
|
||||
needed = sizeof(myf.frdata);
|
||||
}
|
||||
res = read(fds[0], myf.frdata, needed);
|
||||
@@ -251,7 +247,6 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
struct localuser *u;
|
||||
struct sockaddr_in serv_addr;
|
||||
struct hostent *serverhost;
|
||||
struct ast_hostent ahp;
|
||||
int fd;
|
||||
FILE *fs;
|
||||
char *host;
|
||||
@@ -268,9 +263,9 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
int i;
|
||||
struct MD5Context md5ctx;
|
||||
unsigned char MD5Res[16];
|
||||
char MD5Hex[33] = "";
|
||||
char koko[4] = "";
|
||||
char cachefile[MAXFESTLEN]="";
|
||||
char MD5Hex[32];
|
||||
char koko[4];
|
||||
char cachefile[MAXFESTLEN];
|
||||
int readcache=0;
|
||||
int writecache=0;
|
||||
int strln;
|
||||
@@ -305,9 +300,11 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
if (!(festivalcommand = ast_variable_retrieve(cfg, "general", "festivalcommand"))) {
|
||||
festivalcommand = "(tts_textasterisk \"%s\" 'file)(quit)\n";
|
||||
}
|
||||
if (!vdata || ast_strlen_zero(vdata)) {
|
||||
|
||||
|
||||
|
||||
if (!vdata || !strlen(vdata)) {
|
||||
ast_log(LOG_WARNING, "festival requires an argument (text)\n");
|
||||
ast_destroy(cfg);
|
||||
return -1;
|
||||
}
|
||||
strncpy(data, vdata, sizeof(data) - 1);
|
||||
@@ -325,16 +322,14 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
|
||||
if (fd < 0) {
|
||||
ast_log(LOG_WARNING,"festival_client: can't get socket\n");
|
||||
ast_destroy(cfg);
|
||||
return -1;
|
||||
}
|
||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||
if ((serv_addr.sin_addr.s_addr = inet_addr(host)) == -1) {
|
||||
/* its a name rather than an ipnum */
|
||||
serverhost = ast_gethostbyname(host, &ahp);
|
||||
serverhost = gethostbyname(host);
|
||||
if (serverhost == (struct hostent *)0) {
|
||||
ast_log(LOG_WARNING,"festival_client: gethostbyname failed\n");
|
||||
ast_destroy(cfg);
|
||||
return -1;
|
||||
}
|
||||
memmove(&serv_addr.sin_addr,serverhost->h_addr, serverhost->h_length);
|
||||
@@ -344,7 +339,6 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
|
||||
if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) {
|
||||
ast_log(LOG_WARNING,"festival_client: connect to server failed\n");
|
||||
ast_destroy(cfg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -352,21 +346,21 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
MD5Init(&md5ctx);
|
||||
MD5Update(&md5ctx,(unsigned char const *)data,strlen(data));
|
||||
MD5Final(MD5Res,&md5ctx);
|
||||
MD5Hex[0] = '\0';
|
||||
strcpy(MD5Hex,"");
|
||||
|
||||
/* Convert to HEX and look if there is any matching file in the cache
|
||||
directory */
|
||||
for (i=0;i<16;i++) {
|
||||
snprintf(koko, sizeof(koko), "%X",MD5Res[i]);
|
||||
strncat(MD5Hex, koko, sizeof(MD5Hex) - strlen(MD5Hex) - 1);
|
||||
sprintf(koko,"%X",MD5Res[i]);
|
||||
strcat(MD5Hex,koko);
|
||||
}
|
||||
readcache=0;
|
||||
writecache=0;
|
||||
if (strlen(cachedir)+strlen(MD5Hex)+1<=MAXFESTLEN && (usecache==-1)) {
|
||||
snprintf(cachefile, sizeof(cachefile), "%s/%s", cachedir, MD5Hex);
|
||||
sprintf(cachefile,"%s/%s",cachedir,MD5Hex);
|
||||
fdesc=open(cachefile,O_RDWR);
|
||||
if (fdesc==-1) {
|
||||
fdesc=open(cachefile,O_CREAT|O_RDWR,0777);
|
||||
fdesc=open(cachefile,O_CREAT|O_RDWR,0);
|
||||
if (fdesc!=-1) {
|
||||
writecache=1;
|
||||
strln=strlen((char *)data);
|
||||
@@ -378,12 +372,11 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
}
|
||||
} else {
|
||||
read(fdesc,&strln,sizeof(int));
|
||||
ast_log(LOG_DEBUG,"Cache file exists, strln=%d, strlen=%d\n",strln,(int)strlen((char *)data));
|
||||
ast_log(LOG_DEBUG,"Cache file exists, strln=%d, strlen=%d\n",strln,strlen((char *)data));
|
||||
if (strlen((char *)data)==strln) {
|
||||
ast_log(LOG_DEBUG,"Size OK\n");
|
||||
read(fdesc,&bigstring,strln);
|
||||
bigstring[strln] = 0;
|
||||
if (strcmp(bigstring,data)==0) {
|
||||
if (strcmp(bigstring,data)==0) {
|
||||
readcache=1;
|
||||
} else {
|
||||
ast_log(LOG_WARNING,"Strings do not match\n");
|
||||
@@ -447,7 +440,6 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
}
|
||||
} while (strcmp(ack,"OK\n") != 0);
|
||||
close(fd);
|
||||
ast_destroy(cfg);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
|
||||
|
||||
@@ -21,14 +21,11 @@
|
||||
#include <asterisk/image.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <sys/ioctl.h>
|
||||
#ifdef __linux__
|
||||
#include <linux/zaptel.h>
|
||||
#else
|
||||
#include <zaptel.h>
|
||||
#endif /* __linux__ */
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Flash zap trunk application";
|
||||
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Fork CDR application
|
||||
* Copyright Anthony Minessale anthmct@yahoo.com
|
||||
* Development of this app Sponsered/Funded by TAAN Softworks Corp
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/cdr.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Fork The CDR into 2 separate entities.";
|
||||
static char *app = "ForkCDR";
|
||||
static char *synopsis =
|
||||
"Forks the Call Data Record";
|
||||
static char *descrip =
|
||||
" ForkCDR(): Causes the Call Data Record to fork an additional\n"
|
||||
"cdr record starting from the time of the fork call\n";
|
||||
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
|
||||
static void ast_cdr_clone(struct ast_cdr *cdr) {
|
||||
struct ast_cdr *newcdr = ast_cdr_alloc();
|
||||
memcpy(newcdr,cdr,sizeof(struct ast_cdr));
|
||||
ast_cdr_append(cdr,newcdr);
|
||||
gettimeofday(&newcdr->start, NULL);
|
||||
memset(&newcdr->answer, 0, sizeof(newcdr->answer));
|
||||
ast_cdr_add_flag(cdr,AST_CDR_FLAG_CHILD|AST_CDR_FLAG_LOCKED);
|
||||
}
|
||||
|
||||
static void ast_cdr_fork(struct ast_channel *chan) {
|
||||
if(chan && chan->cdr) {
|
||||
ast_cdr_clone(chan->cdr);
|
||||
}
|
||||
}
|
||||
|
||||
static int forkcdr_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
ast_cdr_fork(chan);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, forkcdr_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -3,9 +3,9 @@
|
||||
*
|
||||
* Execute arbitrary system commands
|
||||
*
|
||||
* Copyright (C) 1999-2005, Digium
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
@@ -24,6 +24,9 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "Get ADSI CPE ID";
|
||||
|
||||
static char *app = "GetCPEID";
|
||||
@@ -31,9 +34,9 @@ static char *app = "GetCPEID";
|
||||
static char *synopsis = "Get ADSI CPE ID";
|
||||
|
||||
static char *descrip =
|
||||
" GetCPEID: Obtains and displays ADSI CPE ID and other information in order\n"
|
||||
"to properly setup zapata.conf for on-hook operations.\n"
|
||||
"Returns -1 on hangup only.\n";
|
||||
" GetCPEID: Obtains and displays CPE ID and other information in order to\n"
|
||||
"properly setup zapata.conf for on-hook operations. Returns -1 on hanup\n"
|
||||
"only.";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -67,9 +70,9 @@ static int cpeid_exec(struct ast_channel *chan, void *idata)
|
||||
stuff[2] = data[2];
|
||||
stuff[3] = data[3];
|
||||
memset(data, 0, sizeof(data));
|
||||
strncpy(stuff[0], "** CPE Info **", sizeof(data[0]) - 1);
|
||||
strncpy(stuff[1], "Identifying CPE...", sizeof(data[1]) - 1);
|
||||
strncpy(stuff[2], "Please wait...", sizeof(data[2]) - 1);
|
||||
strcpy(stuff[0], "** CPE Info **");
|
||||
strcpy(stuff[1], "Identifying CPE...");
|
||||
strcpy(stuff[2], "Please wait...");
|
||||
res = adsi_load_session(chan, NULL, 0, 1);
|
||||
if (res > 0) {
|
||||
cpeid_setstatus(chan, stuff, 0);
|
||||
@@ -80,8 +83,8 @@ static int cpeid_exec(struct ast_channel *chan, void *idata)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Got CPEID of '%02x:%02x:%02x:%02x' on '%s'\n", cpeid[0], cpeid[1], cpeid[2], cpeid[3], chan->name);
|
||||
}
|
||||
if (res > -1) {
|
||||
strncpy(stuff[1], "Measuring CPE...", sizeof(data[1]) - 1);
|
||||
strncpy(stuff[2], "Please wait...", sizeof(data[2]) - 1);
|
||||
strcpy(stuff[1], "Measuring CPE...");
|
||||
strcpy(stuff[2], "Please wait...");
|
||||
cpeid_setstatus(chan, stuff, 0);
|
||||
res = adsi_get_cpeinfo(chan, &width, &height, &buttons, 0);
|
||||
if (res > -1) {
|
||||
@@ -92,14 +95,14 @@ static int cpeid_exec(struct ast_channel *chan, void *idata)
|
||||
}
|
||||
if (res > -1) {
|
||||
if (gotcpeid)
|
||||
snprintf(stuff[1], sizeof(data[1]), "CPEID: %02x:%02x:%02x:%02x", cpeid[0], cpeid[1], cpeid[2], cpeid[3]);
|
||||
sprintf(stuff[1], "CPEID: %02x:%02x:%02x:%02x", cpeid[0], cpeid[1], cpeid[2], cpeid[3]);
|
||||
else
|
||||
strncpy(stuff[1], "CPEID Unknown", sizeof(data[1]) - 1);
|
||||
strcpy(stuff[1], "CPEID Unknown");
|
||||
if (gotgeometry)
|
||||
snprintf(stuff[2], sizeof(data[2]), "Geom: %dx%d, %d buttons", width, height, buttons);
|
||||
sprintf(stuff[2], "Geom: %dx%d, %d buttons", width, height, buttons);
|
||||
else
|
||||
strncpy(stuff[2], "Geometry unknown", sizeof(data[2]) - 1);
|
||||
strncpy(stuff[3], "Press # to exit", sizeof(data[3]) - 1);
|
||||
strcpy(stuff[2], "Geometry unknown");
|
||||
strcpy(stuff[3], "Press # to exit");
|
||||
cpeid_setstatus(chan, stuff, 1);
|
||||
for(;;) {
|
||||
res = ast_waitfordigit(chan, 1000);
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Group Manipulation Applications
|
||||
*
|
||||
* Copyright (c) 2004 Digium
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/utils.h>
|
||||
|
||||
static char *tdesc = "Group Management Routines";
|
||||
|
||||
static char *app_group_count = "GetGroupCount";
|
||||
static char *app_group_set = "SetGroup";
|
||||
static char *app_group_check = "CheckGroup";
|
||||
|
||||
static char *group_count_synopsis = "GetGroupCount([groupname][@category])";
|
||||
static char *group_set_synopsis = "SetGroup(groupname[@category])";
|
||||
static char *group_check_synopsis = "CheckGroup(max[@category])";
|
||||
|
||||
static char *group_count_descrip =
|
||||
"GetGroupCount([group][@category])\n"
|
||||
" Calculates the group count for the specified group, or uses\n"
|
||||
"the current channel's group if not specifed (and non-empty).\n"
|
||||
"Stores result in GROUPCOUNT. Always returns 0.\n";
|
||||
|
||||
static char *group_set_descrip =
|
||||
"SetGroup(group)\n"
|
||||
" Sets the channel group to the specified value. Equivalent to\n"
|
||||
"SetVar(GROUP=group). Always returns 0.\n";
|
||||
|
||||
static char *group_check_descrip =
|
||||
"CheckGroup(max)\n"
|
||||
" Checks that the current number of total channels in the\n"
|
||||
"current channel's group does not exceed 'max'. If the number\n"
|
||||
"does not exceed 'max', we continue to the next step. If the\n"
|
||||
"number does in fact exceed max, if priority n+101 exists, then\n"
|
||||
"execution continues at that step, otherwise -1 is returned.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
#define DEFAULT_CATEGORY "GROUP"
|
||||
|
||||
static int group_get_count(char *group, char *category)
|
||||
{
|
||||
struct ast_channel *chan;
|
||||
int count = 0;
|
||||
char *test;
|
||||
if (group && !ast_strlen_zero(group)) {
|
||||
chan = ast_channel_walk_locked(NULL);
|
||||
while(chan) {
|
||||
test = pbx_builtin_getvar_helper(chan, category);
|
||||
if (test && !strcasecmp(test, group))
|
||||
count++;
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
chan = ast_channel_walk_locked(chan);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int group_count_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
int count;
|
||||
struct localuser *u;
|
||||
char *group=NULL;
|
||||
char *cat = NULL;
|
||||
char ret[80]="";
|
||||
char tmp[256]="";
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Check and parse arguments */
|
||||
if (data && !ast_strlen_zero(data)) {
|
||||
strncpy(tmp, data, sizeof(tmp) - 1);
|
||||
group = tmp;
|
||||
cat = strchr(tmp, '@');
|
||||
if (cat) {
|
||||
*cat = '\0';
|
||||
cat++;
|
||||
}
|
||||
}
|
||||
if (cat)
|
||||
snprintf(ret, sizeof(ret), "GROUP_%s", cat);
|
||||
else
|
||||
strncpy(ret, DEFAULT_CATEGORY, sizeof(ret) - 1);
|
||||
|
||||
if (!group || ast_strlen_zero(group)) {
|
||||
group = pbx_builtin_getvar_helper(chan, ret);
|
||||
}
|
||||
count = group_get_count(group, ret);
|
||||
snprintf(ret, sizeof(ret), "%d", count);
|
||||
pbx_builtin_setvar_helper(chan, "GROUPCOUNT", ret);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int group_set_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char ret[80] = "";
|
||||
char tmp[256] = "";
|
||||
char *cat=NULL, *group=NULL;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Check and parse arguments */
|
||||
if (data && !ast_strlen_zero(data)) {
|
||||
strncpy(tmp, data, sizeof(tmp) - 1);
|
||||
group = tmp;
|
||||
cat = strchr(tmp, '@');
|
||||
if (cat) {
|
||||
*cat = '\0';
|
||||
cat++;
|
||||
}
|
||||
}
|
||||
if (cat)
|
||||
snprintf(ret, sizeof(ret), "GROUP_%s", cat);
|
||||
else
|
||||
strncpy(ret, DEFAULT_CATEGORY, sizeof(ret) - 1);
|
||||
|
||||
if (group && !ast_strlen_zero(group)) {
|
||||
pbx_builtin_setvar_helper(chan, ret, group);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "SetGroup requires an argument (group name)\n");
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int group_check_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
int max, count;
|
||||
struct localuser *u;
|
||||
char ret[80] = "";
|
||||
char tmp[256] = "";
|
||||
char *cat, *group;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (data && !ast_strlen_zero(data)) {
|
||||
strncpy(tmp, data, sizeof(tmp) - 1);
|
||||
group = tmp;
|
||||
cat = strchr(tmp, '@');
|
||||
if (cat) {
|
||||
*cat = '\0';
|
||||
cat++;
|
||||
}
|
||||
if ((sscanf((char *)tmp, "%i", &max) == 1) && (max > -1)) {
|
||||
if (cat)
|
||||
snprintf(ret, sizeof(ret), "GROUP_%s", cat);
|
||||
else
|
||||
strncpy(ret, DEFAULT_CATEGORY, sizeof(ret) - 1);
|
||||
|
||||
count = group_get_count(pbx_builtin_getvar_helper(chan, ret), ret);
|
||||
if (count > max) {
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
else
|
||||
res = -1;
|
||||
}
|
||||
} else
|
||||
ast_log(LOG_WARNING, "CheckGroup requires a positive integer argument (max)\n");
|
||||
} else
|
||||
ast_log(LOG_WARNING, "CheckGroup requires an argument(max)\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
res = ast_unregister_application(app_group_count);
|
||||
res |= ast_unregister_application(app_group_set);
|
||||
res |= ast_unregister_application(app_group_check);
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
res = ast_register_application(app_group_count, group_count_exec, group_count_synopsis, group_count_descrip);
|
||||
res |= ast_register_application(app_group_set, group_set_exec, group_set_synopsis, group_set_descrip);
|
||||
res |= ast_register_application(app_group_check, group_check_exec, group_check_synopsis, group_check_descrip);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -1,11 +1,8 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* HasVoicemail application
|
||||
* Changes Copyright (c) 2004 Todd Freeman <freeman@andrews.edu>
|
||||
*
|
||||
* 95% based on HasNewVoicemail by:
|
||||
*
|
||||
* HasNewVoicemail application
|
||||
*
|
||||
* Copyright (c) 2003 Tilghman Lesher. All rights reserved.
|
||||
*
|
||||
* Tilghman Lesher <asterisk-hasnewvoicemail-app@the-tilghman.com>
|
||||
@@ -37,71 +34,56 @@
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "../astconf.h"
|
||||
|
||||
static char *tdesc = "Indicator for whether a voice mailbox has messages in a given folder.";
|
||||
static char *app_hasvoicemail = "HasVoicemail";
|
||||
static char *hasvoicemail_synopsis = "Conditionally branches to priority + 101";
|
||||
static char *hasvoicemail_descrip =
|
||||
"HasVoicemail(vmbox[@context][:folder][|varname])\n"
|
||||
" Branches to priority + 101, if there is voicemail in folder indicated."
|
||||
" Optionally sets <varname> to the number of messages in that folder."
|
||||
" Assumes folder of INBOX if not specified.\n";
|
||||
|
||||
static char *tdesc = "Indicator for whether a voice mailbox has new messages.";
|
||||
static char *app_hasnewvoicemail = "HasNewVoicemail";
|
||||
static char *hasnewvoicemail_synopsis = "Conditionally branches to priority + 101";
|
||||
static char *hasnewvoicemail_descrip =
|
||||
"HasNewVoicemail(vmbox[@context][|varname])\n"
|
||||
" Branches to priority + 101, if there is voicemail in folder INBOX."
|
||||
" Optionally sets <varname> to the number of messages in that folder.\n";
|
||||
" Branches to priority + 101, if there is new voicemail"
|
||||
" Optionally sets <varname> to the number of new messages.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int hasvoicemail_exec(struct ast_channel *chan, void *data)
|
||||
static int hasnewvoicemail_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char vmpath[256], *temps, *input, *varname = NULL, *vmbox, *vmfolder = "INBOX", *context = "default";
|
||||
char vmpath[256], *input, *varname = NULL, *vmbox, *context = "default";
|
||||
DIR *vmdir;
|
||||
struct dirent *vment;
|
||||
int vmcount = 0;
|
||||
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "HasVoicemail requires an argument (vm-box[@context][:folder]|varname)\n");
|
||||
ast_log(LOG_WARNING, "HasNewVoicemail requires an argument (vm-box[@context]|varname)\n");
|
||||
return -1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
input = ast_strdupa((char *)data);
|
||||
if (input) {
|
||||
temps = input;
|
||||
if ((temps = strsep(&input, "|"))) {
|
||||
if (input && !ast_strlen_zero(input))
|
||||
varname = input;
|
||||
input = temps;
|
||||
}
|
||||
if ((temps = strsep(&input, ":"))) {
|
||||
if (input && !ast_strlen_zero(input))
|
||||
vmfolder = input;
|
||||
input = temps;
|
||||
}
|
||||
if ((vmbox = strsep(&input, "@")))
|
||||
if (input && !ast_strlen_zero(input))
|
||||
context = input;
|
||||
if (!vmbox)
|
||||
if ((vmbox = strsep(&input,"|")))
|
||||
varname = input;
|
||||
else
|
||||
vmbox = input;
|
||||
|
||||
snprintf(vmpath,sizeof(vmpath), "%s/voicemail/%s/%s/%s", (char *)ast_config_AST_SPOOL_DIR, context, vmbox, vmfolder);
|
||||
if (index(vmbox,'@')) {
|
||||
context = vmbox;
|
||||
vmbox = strsep(&context,"@");
|
||||
}
|
||||
|
||||
snprintf(vmpath,sizeof(vmpath), "%s/voicemail/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, context, vmbox);
|
||||
if (!(vmdir = opendir(vmpath))) {
|
||||
ast_log(LOG_NOTICE, "Voice mailbox %s at %s does not exist\n", vmbox, vmpath);
|
||||
} else {
|
||||
@@ -115,7 +97,7 @@ static int hasvoicemail_exec(struct ast_channel *chan, void *data)
|
||||
/* Set the count in the channel variable */
|
||||
if (varname) {
|
||||
char tmp[12];
|
||||
snprintf(tmp, sizeof(tmp), "%d", vmcount);
|
||||
snprintf(tmp, sizeof(tmp) - 1, "%d", vmcount);
|
||||
pbx_builtin_setvar_helper(chan, varname, tmp);
|
||||
}
|
||||
|
||||
@@ -136,19 +118,13 @@ static int hasvoicemail_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
res = ast_unregister_application(app_hasvoicemail);
|
||||
res |= ast_unregister_application(app_hasnewvoicemail);
|
||||
return res;
|
||||
return ast_unregister_application(app_hasnewvoicemail);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
res = ast_register_application(app_hasvoicemail, hasvoicemail_exec, hasvoicemail_synopsis, hasvoicemail_descrip);
|
||||
res |= ast_register_application(app_hasnewvoicemail, hasvoicemail_exec, hasnewvoicemail_synopsis, hasnewvoicemail_descrip);
|
||||
return res;
|
||||
return ast_register_application(app_hasnewvoicemail, hasnewvoicemail_exec, hasnewvoicemail_synopsis, hasnewvoicemail_descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
|
||||
196
apps/app_ices.c
196
apps/app_ices.c
@@ -1,196 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Stream to an icecast server via ICES (see contrib/asterisk-ices.xml)
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/frame.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
#include "../astconf.h"
|
||||
|
||||
#define ICES "/usr/bin/ices"
|
||||
#define LOCAL_ICES "/usr/local/bin/ices"
|
||||
|
||||
static char *tdesc = "Encode and Stream via icecast and ices";
|
||||
|
||||
static char *app = "ICES";
|
||||
|
||||
static char *synopsis = "Encode and stream using 'ices'";
|
||||
|
||||
static char *descrip =
|
||||
" ICES(config.xml) Streams to an icecast server using ices\n"
|
||||
"(available separately). A configuration file must be supplied\n"
|
||||
"for ices (see examples/asterisk-ices.conf). Returns -1 on\n"
|
||||
"hangup or 0 otherwise.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int icesencode(char *filename, int fd)
|
||||
{
|
||||
int res;
|
||||
int x;
|
||||
res = fork();
|
||||
if (res < 0)
|
||||
ast_log(LOG_WARNING, "Fork failed\n");
|
||||
if (res)
|
||||
return res;
|
||||
dup2(fd, STDIN_FILENO);
|
||||
for (x=STDERR_FILENO + 1;x<256;x++) {
|
||||
if ((x != STDIN_FILENO) && (x != STDOUT_FILENO))
|
||||
close(x);
|
||||
}
|
||||
/* Most commonly installed in /usr/local/bin */
|
||||
execl(ICES, "ices", filename, (char *)NULL);
|
||||
/* But many places has it in /usr/bin */
|
||||
execl(LOCAL_ICES, "ices", filename, (char *)NULL);
|
||||
/* As a last-ditch effort, try to use PATH */
|
||||
execlp("ices", "ices", filename, (char *)NULL);
|
||||
ast_log(LOG_WARNING, "Execute of ices failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ices_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
int fds[2];
|
||||
int ms = -1;
|
||||
int pid = -1;
|
||||
int flags;
|
||||
int oreadformat;
|
||||
struct timeval last;
|
||||
struct ast_frame *f;
|
||||
char filename[256]="";
|
||||
char *c;
|
||||
last.tv_usec = 0;
|
||||
last.tv_sec = 0;
|
||||
if (!data || !strlen(data)) {
|
||||
ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n");
|
||||
return -1;
|
||||
}
|
||||
if (pipe(fds)) {
|
||||
ast_log(LOG_WARNING, "Unable to create pipe\n");
|
||||
return -1;
|
||||
}
|
||||
flags = fcntl(fds[1], F_GETFL);
|
||||
fcntl(fds[1], F_SETFL, flags | O_NONBLOCK);
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
ast_stopstream(chan);
|
||||
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
res = ast_answer(chan);
|
||||
|
||||
if (res) {
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
ast_log(LOG_WARNING, "Answer failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
oreadformat = chan->readformat;
|
||||
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
|
||||
if (res < 0) {
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
|
||||
return -1;
|
||||
}
|
||||
if (((char *)data)[0] == '/')
|
||||
strncpy(filename, (char *)data, sizeof(filename) - 1);
|
||||
else
|
||||
snprintf(filename, sizeof(filename), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, (char *)data);
|
||||
/* Placeholder for options */
|
||||
c = strchr(filename, '|');
|
||||
if (c)
|
||||
*c = '\0';
|
||||
res = icesencode(filename, fds[0]);
|
||||
close(fds[0]);
|
||||
if (res >= 0) {
|
||||
pid = res;
|
||||
for (;;) {
|
||||
/* Wait for audio, and stream */
|
||||
ms = ast_waitfor(chan, -1);
|
||||
if (ms < 0) {
|
||||
ast_log(LOG_DEBUG, "Hangup detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
res = write(fds[1], f->data, f->datalen);
|
||||
if (res < 0) {
|
||||
if (errno != EAGAIN) {
|
||||
ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno));
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
}
|
||||
close(fds[1]);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
if (pid > -1)
|
||||
kill(pid, SIGKILL);
|
||||
if (!res && oreadformat)
|
||||
ast_set_read_format(chan, oreadformat);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, ices_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <asterisk/image.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Image Transmission Application";
|
||||
|
||||
|
||||
@@ -24,16 +24,16 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#if defined(__linux__)
|
||||
#ifdef __linux__
|
||||
#include <linux/soundcard.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <sys/soundcard.h>
|
||||
#include <machine/soundcard.h>
|
||||
#else
|
||||
#include <soundcard.h>
|
||||
#endif
|
||||
#include <netinet/in.h>
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
#define DEV_DSP "/dev/audio"
|
||||
@@ -58,7 +58,7 @@ STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
AST_MUTEX_DEFINE_STATIC(sound_lock);
|
||||
static ast_mutex_t sound_lock = AST_MUTEX_INITIALIZER;
|
||||
static int sound = -1;
|
||||
|
||||
static int write_audio(short *data, int len)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <asterisk/astdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Look up Caller*ID name/number from blacklist database";
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <asterisk/astdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Look up CallerID Name from local database";
|
||||
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#define MAX_ARGS 80
|
||||
|
||||
static char *tdesc = "Extension Macros";
|
||||
@@ -73,14 +73,14 @@ static int macro_exec(struct ast_channel *chan, void *data)
|
||||
char *save_macro_priority;
|
||||
char *save_macro_offset;
|
||||
|
||||
if (!data || ast_strlen_zero(data)) {
|
||||
if (!data || !strlen(data)) {
|
||||
ast_log(LOG_WARNING, "Invalid Macro incantation\n");
|
||||
return 0;
|
||||
}
|
||||
strncpy(tmp, data, sizeof(tmp) - 1);
|
||||
rest = tmp;
|
||||
macro = strsep(&rest, "|");
|
||||
if (!macro || ast_strlen_zero(macro)) {
|
||||
if (!macro || !strlen(macro)) {
|
||||
ast_log(LOG_WARNING, "Invalid macro name specified\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -96,7 +96,7 @@ static int macro_exec(struct ast_channel *chan, void *data)
|
||||
oldpriority = chan->priority;
|
||||
strncpy(oldexten, chan->exten, sizeof(oldexten) - 1);
|
||||
strncpy(oldcontext, chan->context, sizeof(oldcontext) - 1);
|
||||
if (ast_strlen_zero(chan->macrocontext)) {
|
||||
if (!strlen(chan->macrocontext)) {
|
||||
strncpy(chan->macrocontext, chan->context, sizeof(chan->macrocontext) - 1);
|
||||
strncpy(chan->macroexten, chan->exten, sizeof(chan->macroexten) - 1);
|
||||
chan->macropriority = chan->priority;
|
||||
@@ -122,9 +122,8 @@ static int macro_exec(struct ast_channel *chan, void *data)
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", NULL);
|
||||
|
||||
/* Setup environment for new run */
|
||||
chan->exten[0] = 's';
|
||||
chan->exten[1] = '\0';
|
||||
strncpy(chan->context, fullmacro, sizeof(chan->context) - 1);
|
||||
strcpy(chan->exten, "s");
|
||||
strncpy(chan->context, fullmacro, sizeof(chan->context));
|
||||
chan->priority = 1;
|
||||
|
||||
while((cur = strsep(&rest, "|")) && (argc < MAX_ARGS)) {
|
||||
@@ -140,8 +139,7 @@ static int macro_exec(struct ast_channel *chan, void *data)
|
||||
while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->callerid)) {
|
||||
if ((res = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->callerid))) {
|
||||
/* Something bad happened, or a hangup has been requested. */
|
||||
if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
|
||||
(res == '*') || (res == '#')) {
|
||||
if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F'))) {
|
||||
/* Just return result as to the previous application as if it had been dialed */
|
||||
ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
|
||||
break;
|
||||
@@ -195,8 +193,8 @@ out:
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority);
|
||||
if (save_macro_priority) free(save_macro_priority);
|
||||
if (setmacrocontext) {
|
||||
chan->macrocontext[0] = '\0';
|
||||
chan->macroexten[0] = '\0';
|
||||
strcpy(chan->macrocontext, "");
|
||||
strcpy(chan->macroexten, "");
|
||||
chan->macropriority = 0;
|
||||
}
|
||||
|
||||
@@ -204,7 +202,7 @@ out:
|
||||
/* If we're leaving the macro normally, restore original information */
|
||||
chan->priority = oldpriority;
|
||||
strncpy(chan->context, oldcontext, sizeof(chan->context) - 1);
|
||||
if (!(chan->_softhangup & AST_SOFTHANGUP_ASYNCGOTO)) {
|
||||
if (!chan->_softhangup) {
|
||||
/* Copy the extension, so long as we're not in softhangup, where we could be given an asyncgoto */
|
||||
strncpy(chan->exten, oldexten, sizeof(chan->exten) - 1);
|
||||
if ((offsets = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"))) {
|
||||
|
||||
1228
apps/app_meetme.c
1228
apps/app_meetme.c
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Digital Milliwatt (mu-law) Test Application";
|
||||
|
||||
static char *app = "Milliwatt";
|
||||
@@ -62,7 +64,7 @@ static int milliwatt_generate(struct ast_channel *chan, void *data, int len, int
|
||||
|
||||
if (len > sizeof(buf))
|
||||
{
|
||||
ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",(int)sizeof(buf),len);
|
||||
ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",sizeof(buf),len);
|
||||
len = sizeof(buf);
|
||||
}
|
||||
waste[0] = 0; /* make compiler happy */
|
||||
@@ -74,8 +76,6 @@ static int milliwatt_generate(struct ast_channel *chan, void *data, int len, int
|
||||
wf.datalen = len;
|
||||
wf.samples = wf.datalen;
|
||||
wf.src = "app_milliwatt";
|
||||
wf.delivery.tv_sec = 0;
|
||||
wf.delivery.tv_usec = 0;
|
||||
/* create a buffer containing the digital milliwatt pattern */
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
|
||||
114
apps/app_mp3.c
114
apps/app_mp3.c
@@ -3,9 +3,9 @@
|
||||
*
|
||||
* Silly application to play an MP3 file -- uses mpg123
|
||||
*
|
||||
* Copyright (C) 1999-2004, Digium, Inc.
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define LOCAL_MPG_123 "/usr/local/bin/mpg123"
|
||||
@@ -60,35 +61,36 @@ static int mp3play(char *filename, int fd)
|
||||
close(x);
|
||||
}
|
||||
/* Execute mpg123, but buffer if it's a net connection */
|
||||
if (!strncasecmp(filename, "http://", 7)) {
|
||||
if (strncmp(filename, "http://", 7)) {
|
||||
/* Most commonly installed in /usr/local/bin */
|
||||
execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
/* But many places has it in /usr/bin */
|
||||
execl(MPG_123, "mpg123", "-q", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
execl(MPG_123, "mpg123", "-q", "-s", "-b", "1024", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
/* As a last-ditch effort, try to use PATH */
|
||||
execlp("mpg123", "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
execlp("mpg123", "mpg123", "-q", "-s", "-b", "1024", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
}
|
||||
else {
|
||||
/* Most commonly installed in /usr/local/bin */
|
||||
execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
execl(MPG_123, "mpg123", "-q", "-s", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
/* But many places has it in /usr/bin */
|
||||
execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
/* As a last-ditch effort, try to use PATH */
|
||||
execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
execlp("mpg123", "mpg123", "-q", "-s", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
}
|
||||
ast_log(LOG_WARNING, "Execute of mpg123 failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int timed_read(int fd, void *data, int datalen, int timeout)
|
||||
static int timed_read(int fd, void *data, int datalen)
|
||||
{
|
||||
int res;
|
||||
struct pollfd fds[1];
|
||||
fds[0].fd = fd;
|
||||
fds[0].events = POLLIN;
|
||||
res = poll(fds, 1, timeout);
|
||||
fd_set fds;
|
||||
struct timeval tv = { 2, 0 }; /* Wait no more than 2 seconds */
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
res = ast_select(fd + 1, &fds, NULL, NULL, &tv);
|
||||
if (res < 1) {
|
||||
ast_log(LOG_NOTICE, "Poll timed out/errored out with %d\n", res);
|
||||
ast_log(LOG_NOTICE, "Selected timed out/errored out with %d\n", res);
|
||||
return -1;
|
||||
}
|
||||
return read(fd, data, datalen);
|
||||
@@ -103,14 +105,15 @@ static int mp3_exec(struct ast_channel *chan, void *data)
|
||||
int ms = -1;
|
||||
int pid = -1;
|
||||
int owriteformat;
|
||||
int timeout = 2000;
|
||||
struct timeval now, next;
|
||||
struct timeval last;
|
||||
struct ast_frame *f;
|
||||
struct myframe {
|
||||
struct ast_frame f;
|
||||
char offset[AST_FRIENDLY_OFFSET];
|
||||
short frdata[160];
|
||||
} myf;
|
||||
last.tv_usec = 0;
|
||||
last.tv_sec = 0;
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n");
|
||||
return -1;
|
||||
@@ -129,36 +132,36 @@ static int mp3_exec(struct ast_channel *chan, void *data)
|
||||
return -1;
|
||||
}
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
res = mp3play((char *)data, fds[1]);
|
||||
if (!strncasecmp((char *)data, "http://", 7)) {
|
||||
timeout = 10000;
|
||||
}
|
||||
/* Wait 1000 ms first */
|
||||
next = now;
|
||||
next.tv_sec += 1;
|
||||
ms = 1000;
|
||||
if (res >= 0) {
|
||||
pid = res;
|
||||
/* Order is important -- there's almost always going to be mp3... we want to prioritize the
|
||||
user */
|
||||
for (;;) {
|
||||
gettimeofday(&now, NULL);
|
||||
ms = (next.tv_sec - now.tv_sec) * 1000;
|
||||
ms += (next.tv_usec - now.tv_usec) / 1000;
|
||||
#if 0
|
||||
printf("ms: %d\n", ms);
|
||||
#endif
|
||||
if (ms <= 0) {
|
||||
#if 0
|
||||
{
|
||||
static struct timeval last;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
printf("Since last: %ld\n", (tv.tv_sec - last.tv_sec) * 1000 + (tv.tv_usec - last.tv_usec) / 1000);
|
||||
last = tv;
|
||||
ms = ast_waitfor(chan, ms);
|
||||
if (ms < 0) {
|
||||
ast_log(LOG_DEBUG, "Hangup detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (ms) {
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout);
|
||||
if (f->frametype == AST_FRAME_DTMF) {
|
||||
ast_log(LOG_DEBUG, "User pressed a key\n");
|
||||
ast_frfree(f);
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
ast_frfree(f);
|
||||
} else {
|
||||
res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata));
|
||||
if (res > 0) {
|
||||
myf.f.frametype = AST_FRAME_VOICE;
|
||||
myf.f.subclass = AST_FORMAT_SLINEAR;
|
||||
@@ -167,8 +170,6 @@ static int mp3_exec(struct ast_channel *chan, void *data)
|
||||
myf.f.mallocd = 0;
|
||||
myf.f.offset = AST_FRIENDLY_OFFSET;
|
||||
myf.f.src = __PRETTY_FUNCTION__;
|
||||
myf.f.delivery.tv_sec = 0;
|
||||
myf.f.delivery.tv_usec = 0;
|
||||
myf.f.data = myf.frdata;
|
||||
if (ast_write(chan, &myf.f) < 0) {
|
||||
res = -1;
|
||||
@@ -179,36 +180,7 @@ static int mp3_exec(struct ast_channel *chan, void *data)
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
next.tv_usec += res / 2 * 125;
|
||||
if (next.tv_usec >= 1000000) {
|
||||
next.tv_usec -= 1000000;
|
||||
next.tv_sec++;
|
||||
}
|
||||
#if 0
|
||||
printf("Next: %d\n", ms);
|
||||
#endif
|
||||
} else {
|
||||
ms = ast_waitfor(chan, ms);
|
||||
if (ms < 0) {
|
||||
ast_log(LOG_DEBUG, "Hangup detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (ms) {
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_DTMF) {
|
||||
ast_log(LOG_DEBUG, "User pressed a key\n");
|
||||
ast_frfree(f);
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
ms = res / 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,229 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Silly application to play an NBScat file -- uses nbscat8k
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/frame.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#define LOCAL_NBSCAT "/usr/local/bin/nbscat8k"
|
||||
#define NBSCAT "/usr/bin/nbscat8k"
|
||||
|
||||
static char *tdesc = "Silly NBS Stream Application";
|
||||
|
||||
static char *app = "NBScat";
|
||||
|
||||
static char *synopsis = "Play an NBS local stream";
|
||||
|
||||
static char *descrip =
|
||||
" NBScat: Executes nbscat to listen to the local NBS stream.\n"
|
||||
"Returns -1 on\n hangup or 0 otherwise. User can exit by \n"
|
||||
"pressing any key\n.";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int NBScatplay(int fd)
|
||||
{
|
||||
int res;
|
||||
int x;
|
||||
res = fork();
|
||||
if (res < 0)
|
||||
ast_log(LOG_WARNING, "Fork failed\n");
|
||||
if (res)
|
||||
return res;
|
||||
dup2(fd, STDOUT_FILENO);
|
||||
for (x=0;x<256;x++) {
|
||||
if (x != STDOUT_FILENO)
|
||||
close(x);
|
||||
}
|
||||
/* Most commonly installed in /usr/local/bin */
|
||||
execl(NBSCAT, "nbscat8k", "-d", (char *)NULL);
|
||||
execl(LOCAL_NBSCAT, "nbscat8k", "-d", (char *)NULL);
|
||||
ast_log(LOG_WARNING, "Execute of nbscat8k failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int timed_read(int fd, void *data, int datalen)
|
||||
{
|
||||
int res;
|
||||
struct pollfd fds[1];
|
||||
fds[0].fd = fd;
|
||||
fds[0].events = POLLIN;
|
||||
res = poll(fds, 1, 2000);
|
||||
if (res < 1) {
|
||||
ast_log(LOG_NOTICE, "Selected timed out/errored out with %d\n", res);
|
||||
return -1;
|
||||
}
|
||||
return read(fd, data, datalen);
|
||||
|
||||
}
|
||||
|
||||
static int NBScat_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
int fds[2];
|
||||
int ms = -1;
|
||||
int pid = -1;
|
||||
int owriteformat;
|
||||
struct timeval now, next;
|
||||
struct ast_frame *f;
|
||||
struct myframe {
|
||||
struct ast_frame f;
|
||||
char offset[AST_FRIENDLY_OFFSET];
|
||||
short frdata[160];
|
||||
} myf;
|
||||
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) {
|
||||
ast_log(LOG_WARNING, "Unable to create socketpair\n");
|
||||
return -1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
ast_stopstream(chan);
|
||||
|
||||
owriteformat = chan->writeformat;
|
||||
res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = NBScatplay(fds[1]);
|
||||
/* Wait 1000 ms first */
|
||||
next = now;
|
||||
next.tv_sec += 1;
|
||||
if (res >= 0) {
|
||||
pid = res;
|
||||
/* Order is important -- there's almost always going to be mp3... we want to prioritize the
|
||||
user */
|
||||
for (;;) {
|
||||
gettimeofday(&now, NULL);
|
||||
ms = (next.tv_sec - now.tv_sec) * 1000;
|
||||
ms += (next.tv_usec - now.tv_usec) / 1000;
|
||||
#if 0
|
||||
printf("ms: %d\n", ms);
|
||||
#endif
|
||||
if (ms <= 0) {
|
||||
#if 0
|
||||
{
|
||||
static struct timeval last;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
printf("Since last: %ld\n", (tv.tv_sec - last.tv_sec) * 1000 + (tv.tv_usec - last.tv_usec) / 1000);
|
||||
last = tv;
|
||||
}
|
||||
#endif
|
||||
res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata));
|
||||
if (res > 0) {
|
||||
myf.f.frametype = AST_FRAME_VOICE;
|
||||
myf.f.subclass = AST_FORMAT_SLINEAR;
|
||||
myf.f.datalen = res;
|
||||
myf.f.samples = res / 2;
|
||||
myf.f.mallocd = 0;
|
||||
myf.f.offset = AST_FRIENDLY_OFFSET;
|
||||
myf.f.src = __PRETTY_FUNCTION__;
|
||||
myf.f.delivery.tv_sec = 0;
|
||||
myf.f.delivery.tv_usec = 0;
|
||||
myf.f.data = myf.frdata;
|
||||
if (ast_write(chan, &myf.f) < 0) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_DEBUG, "No more mp3\n");
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
next.tv_usec += res / 2 * 125;
|
||||
if (next.tv_usec >= 1000000) {
|
||||
next.tv_usec -= 1000000;
|
||||
next.tv_sec++;
|
||||
}
|
||||
#if 0
|
||||
printf("Next: %d\n", ms);
|
||||
#endif
|
||||
} else {
|
||||
ms = ast_waitfor(chan, ms);
|
||||
if (ms < 0) {
|
||||
ast_log(LOG_DEBUG, "Hangup detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (ms) {
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_DTMF) {
|
||||
ast_log(LOG_DEBUG, "User pressed a key\n");
|
||||
ast_frfree(f);
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
if (pid > -1)
|
||||
kill(pid, SIGKILL);
|
||||
if (!res && owriteformat)
|
||||
ast_set_write_format(chan, owriteformat);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, NBScat_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -1,277 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Time of day - Report the time of day
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/config.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/causes.h>
|
||||
#include <asterisk/astosp.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static char *tdesc = "OSP Lookup";
|
||||
|
||||
static char *app = "OSPLookup";
|
||||
static char *app2 = "OSPNext";
|
||||
static char *app3 = "OSPFinish";
|
||||
|
||||
static char *synopsis = "Lookup number in OSP";
|
||||
static char *synopsis2 = "Lookup next OSP entry";
|
||||
static char *synopsis3 = "Record OSP entry";
|
||||
|
||||
static char *descrip =
|
||||
" OSPLookup(exten[|provider[|options]]): Looks up an extension via OSP and sets\n"
|
||||
"the variables, where 'n' is the number of the result beginning with 1:\n"
|
||||
" ${OSPTECH}: The technology to use for the call\n"
|
||||
" ${OSPDEST}: The destination to use for the call\n"
|
||||
" ${OSPTOKEN}: The actual OSP token as a string\n"
|
||||
" ${OSPHANDLE}: The OSP Handle for anything remaining\n"
|
||||
" ${OSPRESULTS}: The number of OSP results total remaining\n"
|
||||
"\n"
|
||||
"If the lookup was *not* successful and there exists a priority n + 101,\n"
|
||||
"then that priority will be taken next.\n" ;
|
||||
|
||||
static char *descrip2 =
|
||||
" OSPNext: Looks up the next OSP Destination for ${OSPHANDLE}\n"
|
||||
"See OSPLookup for more information\n"
|
||||
"\n"
|
||||
"If the lookup was *not* successful and there exists a priority n + 101,\n"
|
||||
"then that priority will be taken next.\n" ;
|
||||
|
||||
static char *descrip3 =
|
||||
" OSPFinish(status): Records call state for ${OSPHANDLE}, according to\n"
|
||||
"status, which should be one of BUSY, CONGESTION, ANSWER, NOANSWER, or NOCHANAVAIL\n"
|
||||
"or coincidentally, just what the Dial application stores in its ${DIALSTATUS}\n"
|
||||
"\n"
|
||||
"If the finishing was *not* successful and there exists a priority n + 101,\n"
|
||||
"then that priority will be taken next.\n" ;
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int str2cause(char *cause)
|
||||
{
|
||||
if (!strcasecmp(cause, "BUSY"))
|
||||
return AST_CAUSE_BUSY;
|
||||
if (!strcasecmp(cause, "CONGESTION"))
|
||||
return AST_CAUSE_CONGESTION;
|
||||
if (!strcasecmp(cause, "ANSWER"))
|
||||
return AST_CAUSE_NORMAL;
|
||||
if (!strcasecmp(cause, "CANCEL"))
|
||||
return AST_CAUSE_NORMAL;
|
||||
if (!strcasecmp(cause, "NOANSWER"))
|
||||
return AST_CAUSE_NOANSWER;
|
||||
if (!strcasecmp(cause, "NOCHANAVAIL"))
|
||||
return AST_CAUSE_CONGESTION;
|
||||
ast_log(LOG_WARNING, "Unknown cause '%s', using NORMAL\n", cause);
|
||||
return AST_CAUSE_NORMAL;
|
||||
}
|
||||
|
||||
static int osplookup_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *temp;
|
||||
char *provider, *opts=NULL;
|
||||
struct ast_osp_result result;
|
||||
if (!data || ast_strlen_zero(data) || !(temp = ast_strdupa(data))) {
|
||||
ast_log(LOG_WARNING, "OSPLookup requires an argument (extension)\n");
|
||||
return -1;
|
||||
}
|
||||
provider = strchr(temp, '|');
|
||||
if (provider) {
|
||||
*provider = '\0';
|
||||
provider++;
|
||||
opts = strchr(provider, '|');
|
||||
if (opts) {
|
||||
*opts = '\0';
|
||||
opts++;
|
||||
}
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
ast_log(LOG_DEBUG, "Whoo hoo, looking up OSP on '%s' via '%s'\n", temp, provider ? provider : "<default>");
|
||||
if ((res = ast_osp_lookup(chan, provider, temp, chan->callerid, &result)) > 0) {
|
||||
char tmp[80];
|
||||
snprintf(tmp, sizeof(tmp), "%d", result.handle);
|
||||
pbx_builtin_setvar_helper(chan, "OSPHANDLE", tmp);
|
||||
pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
|
||||
pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
|
||||
pbx_builtin_setvar_helper(chan, "OSPTOKEN", result.token);
|
||||
snprintf(tmp, sizeof(tmp), "%d", result.numresults);
|
||||
pbx_builtin_setvar_helper(chan, "OSPRESULTS", tmp);
|
||||
} else {
|
||||
if (!res)
|
||||
ast_log(LOG_NOTICE, "OSP Lookup failed for '%s' (provider '%s')\n", temp, provider ? provider : "<default>");
|
||||
else
|
||||
ast_log(LOG_DEBUG, "Got hangup on '%s' while doing OSP Lookup for '%s' (provider '%s')!\n", chan->name, temp, provider ? provider : "<default>" );
|
||||
}
|
||||
if (!res) {
|
||||
/* Look for a "busy" place */
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
} else if (res > 0)
|
||||
res = 0;
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int ospnext_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *temp;
|
||||
int cause;
|
||||
struct ast_osp_result result;
|
||||
if (!data || ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "OSPNext should have an argument (cause)\n");
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
cause = str2cause((char *)data);
|
||||
temp = pbx_builtin_getvar_helper(chan, "OSPHANDLE");
|
||||
result.handle = -1;
|
||||
if (temp && strlen(temp) && (sscanf(temp, "%i", &result.handle) == 1) && (result.handle > -1)) {
|
||||
if ((res = ast_osp_next(&result, cause)) > 0) {
|
||||
char tmp[80];
|
||||
snprintf(tmp, sizeof(tmp), "%d", result.handle);
|
||||
pbx_builtin_setvar_helper(chan, "OSPHANDLE", tmp);
|
||||
pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
|
||||
pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
|
||||
pbx_builtin_setvar_helper(chan, "OSPTOKEN", result.token);
|
||||
snprintf(tmp, sizeof(tmp), "%d", result.numresults);
|
||||
pbx_builtin_setvar_helper(chan, "OSPRESULTS", tmp);
|
||||
}
|
||||
} else {
|
||||
if (!res) {
|
||||
if (result.handle < 0)
|
||||
ast_log(LOG_NOTICE, "OSP Lookup Next failed for handle '%d'\n", result.handle);
|
||||
else
|
||||
ast_log(LOG_DEBUG, "No OSP handle specified\n");
|
||||
} else
|
||||
ast_log(LOG_DEBUG, "Got hangup on '%s' while doing OSP Next!\n", chan->name);
|
||||
}
|
||||
if (!res) {
|
||||
/* Look for a "busy" place */
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
} else if (res > 0)
|
||||
res = 0;
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int ospfinished_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *temp;
|
||||
int cause;
|
||||
time_t start=0, duration=0;
|
||||
struct ast_osp_result result;
|
||||
if (!data || ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "OSPFinish should have an argument (cause)\n");
|
||||
}
|
||||
if (chan->cdr) {
|
||||
start = chan->cdr->answer.tv_sec;
|
||||
if (start)
|
||||
duration = time(NULL) - start;
|
||||
else
|
||||
duration = 0;
|
||||
} else
|
||||
ast_log(LOG_WARNING, "OSPFinish called on channel '%s' with no CDR!\n", chan->name);
|
||||
LOCAL_USER_ADD(u);
|
||||
cause = str2cause((char *)data);
|
||||
temp = pbx_builtin_getvar_helper(chan, "OSPHANDLE");
|
||||
result.handle = -1;
|
||||
if (temp && strlen(temp) && (sscanf(temp, "%i", &result.handle) == 1) && (result.handle > -1)) {
|
||||
if (!ast_osp_terminate(result.handle, cause, start, duration)) {
|
||||
pbx_builtin_setvar_helper(chan, "OSPHANDLE", "");
|
||||
res = 1;
|
||||
}
|
||||
} else {
|
||||
if (!res) {
|
||||
if (result.handle > -1)
|
||||
ast_log(LOG_NOTICE, "OSP Finish failed for handle '%d'\n", result.handle);
|
||||
else
|
||||
ast_log(LOG_DEBUG, "No OSP handle specified\n");
|
||||
} else
|
||||
ast_log(LOG_DEBUG, "Got hangup on '%s' while doing OSP Terminate!\n", chan->name);
|
||||
}
|
||||
if (!res) {
|
||||
/* Look for a "busy" place */
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
} else if (res > 0)
|
||||
res = 0;
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
res = ast_unregister_application(app3);
|
||||
res |= ast_unregister_application(app2);
|
||||
res |= ast_unregister_application(app);
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
res = ast_register_application(app, osplookup_exec, synopsis, descrip);
|
||||
if (res)
|
||||
return(res);
|
||||
res = ast_register_application(app2, ospnext_exec, synopsis2, descrip2);
|
||||
if (res)
|
||||
return(res);
|
||||
res = ast_register_application(app3, ospfinished_exec, synopsis3, descrip3);
|
||||
if (res)
|
||||
return(res);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int reload(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
@@ -21,17 +21,18 @@
|
||||
#include <asterisk/channel_pvt.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/features.h>
|
||||
#include <asterisk/parking.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/say.h>
|
||||
#include <asterisk/lock.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Call Parking and Announce Application";
|
||||
|
||||
static char *app = "ParkAndAnnounce";
|
||||
@@ -41,7 +42,7 @@ static char *synopsis = "Park and Announce";
|
||||
static char *descrip =
|
||||
" ParkAndAnnounce(announce:template|timeout|dial|[return_context]):\n"
|
||||
"Park a call into the parkinglot and announce the call over the console.\n"
|
||||
"announce template: colon separated list of files to announce, the word PARKED\n"
|
||||
"announce template: colon seperated list of files to announce, the word PARKED\n"
|
||||
" will be replaced by a say_digits of the ext the call is parked in\n"
|
||||
"timeout: time in seconds before the call returns into the return context.\n"
|
||||
"dial: The app_dial style resource to call to make the announcement. Console/dsp calls the console.\n"
|
||||
@@ -54,171 +55,170 @@ LOCAL_USER_DECL;
|
||||
|
||||
static int parkandannounce_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
char *return_context;
|
||||
int l, lot, timeout = 0, dres;
|
||||
char *working, *context, *exten, *priority, *dial, *dialtech, *dialstr;
|
||||
char *template, *tpl_working, *tpl_current;
|
||||
char *tmp[100];
|
||||
int looptemp=0,i=0;
|
||||
char *s,*orig_s;
|
||||
int res=0;
|
||||
char *return_context;
|
||||
int l, lot, timeout, dres;
|
||||
char *working, *context, *exten, *priority, *dial, *dialtech, *dialstr;
|
||||
char *template, *tpl_working, *tpl_current;
|
||||
char *tmp[100];
|
||||
int looptemp=0,i=0;
|
||||
char *s,*orig_s;
|
||||
|
||||
struct ast_channel *dchan;
|
||||
int outstate;
|
||||
struct ast_channel *dchan;
|
||||
int outstate;
|
||||
|
||||
struct localuser *u;
|
||||
if(!data || (data && !strlen(data))) {
|
||||
ast_log(LOG_WARNING, "ParkAndAnnounce requires arguments: (announce:template|timeout|dial|[return_context])\n");
|
||||
return -1;
|
||||
}
|
||||
struct localuser *u;
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "Park requires an argument (parkinglot)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
l=strlen(data)+2;
|
||||
orig_s=malloc(l);
|
||||
if(!orig_s) {
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
s=orig_s;
|
||||
strncpy(s,data,l);
|
||||
l=strlen(data)+2;
|
||||
orig_s=malloc(l);
|
||||
s=orig_s;
|
||||
strncpy(s,data,l);
|
||||
|
||||
template=strsep(&s,"|");
|
||||
if(! template) {
|
||||
ast_log(LOG_WARNING, "PARK: An announce template must be defined\n");
|
||||
free(orig_s);
|
||||
return -1;
|
||||
}
|
||||
template=strsep(&s,"|");
|
||||
if (! template) {
|
||||
ast_log(LOG_WARNING, "PARK: An announce template must be defined\n");
|
||||
free(orig_s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(s) {
|
||||
timeout = atoi(strsep(&s, "|"));
|
||||
timeout *= 1000;
|
||||
}
|
||||
dial=strsep(&s, "|");
|
||||
if(!dial) {
|
||||
ast_log(LOG_WARNING, "PARK: A dial resource must be specified i.e: Console/dsp or Zap/g1/5551212\n");
|
||||
free(orig_s);
|
||||
return -1;
|
||||
} else {
|
||||
dialtech=strsep(&dial, "/");
|
||||
dialstr=dial;
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Dial Tech,String: (%s,%s)\n", dialtech,dialstr);
|
||||
}
|
||||
timeout = atoi(strsep(&s, "|"));
|
||||
timeout *= 1000;
|
||||
|
||||
return_context = s;
|
||||
dial=strsep(&s, "|");
|
||||
if (! dial) {
|
||||
ast_log(LOG_WARNING, "PARK: A dial resouce must be specified i.e: Console/dsp or Zap/g1/5551212\n");
|
||||
free(orig_s);
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
dialtech=strsep(&dial, "/");
|
||||
dialstr=dial;
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Dial Tech,String: (%s,%s)\n", dialtech,dialstr);
|
||||
}
|
||||
|
||||
return_context = s;
|
||||
|
||||
if(return_context != NULL) {
|
||||
/* set the return context. Code borrowed from the Goto builtin */
|
||||
if (return_context != NULL) {
|
||||
/* set the return context. Code borrowed from the Goto builtin */
|
||||
|
||||
working = return_context;
|
||||
context = strsep(&working, "|");
|
||||
exten = strsep(&working, "|");
|
||||
if(!exten) {
|
||||
/* Only a priority in this one */
|
||||
priority = context;
|
||||
exten = NULL;
|
||||
context = NULL;
|
||||
} else {
|
||||
priority = strsep(&working, "|");
|
||||
if(!priority) {
|
||||
/* Only an extension and priority in this one */
|
||||
priority = exten;
|
||||
exten = context;
|
||||
context = NULL;
|
||||
}
|
||||
}
|
||||
if(atoi(priority) < 0) {
|
||||
ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
|
||||
free(orig_s);
|
||||
return -1;
|
||||
}
|
||||
/* At this point we have a priority and maybe an extension and a context */
|
||||
chan->priority = atoi(priority);
|
||||
if(exten && strcasecmp(exten, "BYEXTENSION"))
|
||||
strncpy(chan->exten, exten, sizeof(chan->exten)-1);
|
||||
if(context)
|
||||
strncpy(chan->context, context, sizeof(chan->context)-1);
|
||||
} else { /* increment the priority by default*/
|
||||
chan->priority++;
|
||||
}
|
||||
working = return_context;
|
||||
context = strsep(&working, "|");
|
||||
exten = strsep(&working, "|");
|
||||
if (!exten) {
|
||||
/* Only a priority in this one */
|
||||
priority = context;
|
||||
exten = NULL;
|
||||
context = NULL;
|
||||
} else {
|
||||
priority = strsep(&working, "|");
|
||||
if (!priority) {
|
||||
/* Only an extension and priority in this one */
|
||||
priority = exten;
|
||||
exten = context;
|
||||
context = NULL;
|
||||
}
|
||||
}
|
||||
if (atoi(priority) < 0) {
|
||||
ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
|
||||
free(orig_s);
|
||||
return -1;
|
||||
}
|
||||
/* At this point we have a priority and maybe an extension and a context */
|
||||
chan->priority = atoi(priority);
|
||||
if (exten && strcasecmp(exten, "BYEXTENSION"))
|
||||
strncpy(chan->exten, exten, sizeof(chan->exten)-1);
|
||||
if (context)
|
||||
strncpy(chan->context, context, sizeof(chan->context)-1);
|
||||
}
|
||||
else { /* increment the priority by default*/
|
||||
chan->priority++;
|
||||
}
|
||||
|
||||
|
||||
if(option_verbose > 2) {
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->callerid);
|
||||
if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->callerid)) {
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
|
||||
}
|
||||
}
|
||||
if (option_verbose > 2) {
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->callerid);
|
||||
if (!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->callerid)) {
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
|
||||
}
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* we are using masq_park here to protect * from touching the channel once we park it. If the channel comes out of timeout
|
||||
before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */
|
||||
/* we are using masq_park here to protect * from touching the channel once we park it. If the channel comes out of timeout
|
||||
before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */
|
||||
|
||||
ast_masq_park_call(chan, NULL, timeout, &lot);
|
||||
ast_masq_park_call(chan, NULL, timeout, &lot);
|
||||
|
||||
res=-1;
|
||||
res=-1;
|
||||
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
|
||||
|
||||
/* Now place the call to the extention */
|
||||
/* Now place the call to the extention */
|
||||
|
||||
dchan = ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->callerid);
|
||||
dchan = ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->callerid);
|
||||
|
||||
if(dchan) {
|
||||
if(dchan->_state == AST_STATE_UP) {
|
||||
if(option_verbose > 3)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", dchan->name);
|
||||
} else {
|
||||
if(option_verbose > 3)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", dchan->name);
|
||||
ast_log(LOG_WARNING, "PARK: Channel %s was never answered for the announce.\n", dchan->name);
|
||||
ast_hangup(dchan);
|
||||
free(orig_s);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "PARK: Unable to allocate announce channel.\n");
|
||||
free(orig_s);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
if (dchan) {
|
||||
if (dchan->_state == AST_STATE_UP) {
|
||||
if (option_verbose > 3)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", dchan->name);
|
||||
} else {
|
||||
if (option_verbose > 3)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", dchan->name);
|
||||
ast_log(LOG_WARNING, "PARK: Channel %s was never answered for the announce.\n", dchan->name);
|
||||
ast_hangup(dchan);
|
||||
free(orig_s);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ast_log(LOG_WARNING, "PARK: Unable to allocate announce channel.\n");
|
||||
free(orig_s);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ast_stopstream(dchan);
|
||||
ast_stopstream(dchan);
|
||||
|
||||
/* now we have the call placed and are ready to play stuff to it */
|
||||
/* now we have the call placed and are ready to play stuff to it */
|
||||
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Announce Template:%s\n", template);
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Announce Template:%s\n", template);
|
||||
|
||||
tpl_working = template;
|
||||
tpl_current=strsep(&tpl_working, ":");
|
||||
tpl_working = template;
|
||||
tpl_current=strsep(&tpl_working, ":");
|
||||
|
||||
while(tpl_current && looptemp < sizeof(tmp)) {
|
||||
tmp[looptemp]=tpl_current;
|
||||
looptemp++;
|
||||
tpl_current=strsep(&tpl_working,":");
|
||||
}
|
||||
while ( tpl_current && looptemp < sizeof(tmp)) {
|
||||
tmp[looptemp]=tpl_current;
|
||||
looptemp++;
|
||||
tpl_current=strsep(&tpl_working,":");
|
||||
}
|
||||
|
||||
for(i=0; i<looptemp; i++) {
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Announce:%s\n", tmp[i]);
|
||||
if(!strcmp(tmp[i], "PARKED")) {
|
||||
ast_say_digits(dchan, lot, "", dchan->language);
|
||||
} else {
|
||||
dres = ast_streamfile(dchan, tmp[i], dchan->language);
|
||||
if(!dres) {
|
||||
dres = ast_waitstream(dchan, "");
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], dchan->name);
|
||||
dres = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(i=0; i<looptemp; i++) {
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Announce:%s\n", tmp[i]);
|
||||
if (!strcmp(tmp[i], "PARKED")) {
|
||||
ast_say_digits(dchan, lot, "", dchan->language);
|
||||
}
|
||||
else {
|
||||
dres = ast_streamfile(dchan, tmp[i], dchan->language);
|
||||
if (!dres)
|
||||
dres = ast_waitstream(dchan, "");
|
||||
else {
|
||||
ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], dchan->name);
|
||||
dres = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ast_stopstream(dchan);
|
||||
ast_hangup(dchan);
|
||||
ast_stopstream(dchan);
|
||||
ast_hangup(dchan);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
free(orig_s);
|
||||
return res;
|
||||
LOCAL_USER_REMOVE(u);
|
||||
free(orig_s);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -231,8 +231,8 @@ int unload_module(void)
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
/* return ast_register_application(app, park_exec); */
|
||||
return ast_register_application(app, parkandannounce_exec, synopsis, descrip);
|
||||
/* return ast_register_application(app, park_exec); */
|
||||
return ast_register_application(app, parkandannounce_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Trivial Playback Application";
|
||||
|
||||
@@ -30,14 +30,14 @@ static char *synopsis = "Play a file";
|
||||
|
||||
static char *descrip =
|
||||
" Playback(filename[|option]): Plays back a given filename (do not put\n"
|
||||
"extension). Options may also be included following a pipe symbol. The 'skip'\n"
|
||||
"option causes the playback of the message to be skipped if the channel\n"
|
||||
"is not in the 'up' state (i.e. it hasn't been answered yet. If 'skip' is \n"
|
||||
"specified, the application will return immediately should the channel not be\n"
|
||||
"off hook. Otherwise, unless 'noanswer' is specified, the channel channel will\n"
|
||||
"be answered before the sound is played. Not all channels support playing\n"
|
||||
"messages while still hook. Returns -1 if the channel was hung up, or if the\n"
|
||||
"file does not exist. Returns 0 otherwise.\n";
|
||||
"extension). Options may also be included following a pipe symbol. The only\n"
|
||||
"defined option at this time is 'skip', which causes the playback of the\n"
|
||||
"message to be skipped if the channel is not in the 'up' state (i.e. it\n"
|
||||
"hasn't been answered yet. If 'skip' is specified, the application will\n"
|
||||
"return immediately should the channel not be off hook. Otherwise, unless\n"
|
||||
"'noanswer' is specified, the channel channel will be answered before the sound\n"
|
||||
"is played. Not all channels support playing messages while on hook. Returns -1\n"
|
||||
"if the channel was hung up, or if the file does not exist. Returns 0 otherwise.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -52,7 +52,7 @@ static int playback_exec(struct ast_channel *chan, void *data)
|
||||
int option_skip=0;
|
||||
int option_noanswer = 0;
|
||||
char *stringp;
|
||||
if (!data || ast_strlen_zero((char *)data)) {
|
||||
if (!data || !strlen((char *)data)) {
|
||||
ast_log(LOG_WARNING, "Playback requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <asterisk/config.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define PRIV_CONFIG "privacy.conf"
|
||||
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
@@ -63,6 +62,7 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
@@ -123,7 +123,7 @@ pthread_attr_t attr;
|
||||
while((dp = readdir(dirp)) != NULL)
|
||||
{
|
||||
if (dp->d_name[0] == '.') continue;
|
||||
snprintf(fname, sizeof(fname), "%s/%s", qdir, dp->d_name);
|
||||
sprintf(fname,"%s/%s",qdir,dp->d_name);
|
||||
if (stat(fname,&mystat) == -1)
|
||||
{
|
||||
perror("app_qcall:stat");
|
||||
@@ -157,7 +157,7 @@ pthread_attr_t attr;
|
||||
arg = (void *) strdup(fname);
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
if (ast_pthread_create(&dialer_thread,&attr,qcall_do,arg) == -1)
|
||||
if (pthread_create(&dialer_thread,&attr,qcall_do,arg) == -1)
|
||||
{
|
||||
perror("qcall: Cannot create thread");
|
||||
continue;
|
||||
@@ -172,20 +172,15 @@ pthread_attr_t attr;
|
||||
/* single thread with one file (request) to dial */
|
||||
static void *qcall_do(void *arg)
|
||||
{
|
||||
char fname[300] = "";
|
||||
char dialstr[300];
|
||||
char extstr[300];
|
||||
char ident[300] = "";
|
||||
char reqinp[300] = "";
|
||||
char buf[300];
|
||||
char clid[300],*tele,*context;
|
||||
FILE *fp;
|
||||
int ms = MAXWAITFORANSWER,maxsecs;
|
||||
struct ast_channel *channel;
|
||||
time_t t;
|
||||
char fname[300],dialstr[300],extstr[300],ident[300],reqinp[300],buf[300];
|
||||
char clid[300],*tele,*context;
|
||||
FILE *fp;
|
||||
int ms = MAXWAITFORANSWER,maxsecs;
|
||||
struct ast_channel *channel;
|
||||
time_t t;
|
||||
|
||||
/* get the filename from the arg */
|
||||
strncpy(fname,(char *)arg, sizeof(fname) - 1);
|
||||
strcpy(fname,(char *)arg);
|
||||
free(arg);
|
||||
time(&t);
|
||||
fp = fopen(fname,"r");
|
||||
@@ -203,11 +198,8 @@ static void *qcall_do(void *arg)
|
||||
fprintf(stderr,"%s\n",fname);
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
/* default required input for acknowledgement */
|
||||
reqinp[0] = '1';
|
||||
reqinp[1] = '\0';
|
||||
/* default no ident */
|
||||
ident[0] = '\0'; /* default no ident */
|
||||
strcpy(reqinp,"1"); /* default required input for acknowledgement */
|
||||
strcpy(ident, ""); /* default no ident */
|
||||
if (fscanf(fp,"%s %s %s %d %s %s",dialstr,clid,
|
||||
extstr,&maxsecs,ident,reqinp) < 4)
|
||||
{
|
||||
@@ -316,7 +308,7 @@ static void *qcall_do(void *arg)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Qcall got accept, now putting through to %s@%s on %s\n",
|
||||
extstr,context,channel->name);
|
||||
if (strlen(ident)) {
|
||||
strncat(ident,"-ok", sizeof(ident) - strlen(ident) - 1);
|
||||
strcat(ident,"-ok");
|
||||
/* if file existant, play it */
|
||||
if (!ast_streamfile(channel,ident,0))
|
||||
{
|
||||
@@ -334,7 +326,7 @@ static void *qcall_do(void *arg)
|
||||
channel->amaflags = AMAFLAGS;
|
||||
#endif
|
||||
#ifdef ACCTCODE
|
||||
strncpy(channel->accountcode, ACCTCODE, sizeof(chan->accountcode) - 1);
|
||||
strcpy(channel->accountcode,ACCTCODE);
|
||||
#else
|
||||
channel->accountcode[0] = 0;
|
||||
#endif
|
||||
@@ -343,10 +335,10 @@ static void *qcall_do(void *arg)
|
||||
time(&channel->whentohangup);
|
||||
channel->whentohangup += maxsecs;
|
||||
}
|
||||
strncpy(channel->exten, extstr, sizeof(channel->exten) - 1);
|
||||
strncpy(channel->context, context, sizeof(channel->context) - 1);
|
||||
strcpy(channel->exten,extstr);
|
||||
strcpy(channel->context,context);
|
||||
channel->priority = 1;
|
||||
if(debug) printf("Caller ID is %s\n", channel->callerid);
|
||||
printf("Caller ID is %s\n", channel->callerid);
|
||||
ast_pbx_run(channel);
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
@@ -370,9 +362,9 @@ int unload_module(void)
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
snprintf(qdir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "qcall");
|
||||
snprintf((char *)qdir,sizeof(qdir)-1,"%s/%s",(char *)ast_config_AST_SPOOL_DIR,"qcall");
|
||||
mkdir(qdir,0760);
|
||||
ast_pthread_create(&qcall_thread,NULL,qcall,NULL);
|
||||
pthread_create(&qcall_thread,NULL,qcall,NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
1492
apps/app_queue.c
1492
apps/app_queue.c
File diff suppressed because it is too large
Load Diff
@@ -42,7 +42,7 @@ static int random_exec(struct ast_channel *chan, void *data)
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
|
||||
char *s;
|
||||
char *s, *ts;
|
||||
char *exten, *pri, *context;
|
||||
char *prob;
|
||||
int probint, priorityint;
|
||||
@@ -54,7 +54,7 @@ static int random_exec(struct ast_channel *chan, void *data)
|
||||
LOCAL_USER_ADD(u);
|
||||
s = ast_strdupa((void *) data);
|
||||
|
||||
prob = strsep(&s,":");
|
||||
prob = strsep(&ts,":");
|
||||
if ((!prob) || (sscanf(prob, "%d", &probint) != 1))
|
||||
probint = 0;
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Read Variable Application";
|
||||
|
||||
@@ -31,17 +31,9 @@ static char *app = "Read";
|
||||
static char *synopsis = "Read a variable";
|
||||
|
||||
static char *descrip =
|
||||
" Read(variable[|filename][|maxdigits][|option])\n\n"
|
||||
"Reads a #-terminated string of digits from the user in to the given variable,\n"
|
||||
"optionally playing a given filename first.\n"
|
||||
" maxdigits -- maximum acceptable number of digits. Stops reading after\n"
|
||||
" maxdigits have been entered (without requiring the user to\n"
|
||||
" press the '#' key).\n"
|
||||
" Defaults to 0 - no limit - wait for the user press the '#' key.\n"
|
||||
" Any value below 0 means the same. Max accepted value is 255.\n"
|
||||
" option -- may be 'skip' to return immediately if the line is not up,\n"
|
||||
" or 'noanswer' to read digits even if the line is not up.\n\n"
|
||||
"Returns -1 on hangup or error and 0 otherwise.\n";
|
||||
" Read(variable[|filename]): Reads a '#' terminated string of digits from\n"
|
||||
"the user, optionally playing a given filename first. Returns -1 on hangup or\n"
|
||||
"error and 0 otherwise.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -52,64 +44,32 @@ static int read_exec(struct ast_channel *chan, void *data)
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
char tmp[256];
|
||||
char argdata[256] = "";
|
||||
char *varname;
|
||||
char tmp2[128]="";
|
||||
char *filename;
|
||||
char *stringp;
|
||||
char *maxdigitstr;
|
||||
char *options;
|
||||
int option_skip = 0;
|
||||
int option_noanswer = 0;
|
||||
int maxdigits=255;
|
||||
if (!data || ast_strlen_zero((char *)data)) {
|
||||
if (!data || !strlen((char *)data)) {
|
||||
ast_log(LOG_WARNING, "Read requires an argument (variable)\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(argdata, (char *)data, sizeof(argdata)-1);
|
||||
stringp=argdata;
|
||||
varname = strsep(&stringp, "|");
|
||||
strncpy(tmp, (char *)data, sizeof(tmp)-1);
|
||||
stringp=tmp;
|
||||
strsep(&stringp, "|");
|
||||
filename = strsep(&stringp, "|");
|
||||
maxdigitstr = strsep(&stringp,"|");
|
||||
options = strsep(&stringp, "|");
|
||||
if (options && !strcasecmp(options, "skip"))
|
||||
option_skip = 1;
|
||||
if (options && !strcasecmp(options, "noanswer"))
|
||||
option_noanswer = 1;
|
||||
if (!(filename) || ast_strlen_zero(filename))
|
||||
filename = NULL;
|
||||
if (maxdigitstr) {
|
||||
maxdigits = atoi(maxdigitstr);
|
||||
if ((maxdigits<1) || (maxdigits>255)) {
|
||||
maxdigits = 255;
|
||||
} else
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Accepting a maximum of %i digits.\n", maxdigits);
|
||||
}
|
||||
if (!(varname) || ast_strlen_zero(varname)) {
|
||||
if (!strlen(tmp)) {
|
||||
ast_log(LOG_WARNING, "Read requires an variable name\n");
|
||||
return -1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
if (option_skip) {
|
||||
/* At the user's option, skip if the line is not up */
|
||||
pbx_builtin_setvar_helper(chan, varname, "\0");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
} else if (!option_noanswer) {
|
||||
/* Otherwise answer unless we're supposed to read while on-hook */
|
||||
res = ast_answer(chan);
|
||||
}
|
||||
/* Answer if the line isn't up. */
|
||||
res = ast_answer(chan);
|
||||
}
|
||||
if (!res) {
|
||||
ast_stopstream(chan);
|
||||
res = ast_app_getdata(chan, filename, tmp, maxdigits, 0);
|
||||
if (res > -1) {
|
||||
pbx_builtin_setvar_helper(chan, varname, tmp);
|
||||
ast_verbose(VERBOSE_PREFIX_3 "User entered '%s'\n", tmp);
|
||||
res = 0;
|
||||
} else {
|
||||
ast_verbose(VERBOSE_PREFIX_3 "User disconnected\n");
|
||||
}
|
||||
res = ast_app_getdata(chan, filename, tmp2, sizeof(tmp2) - 1, 0);
|
||||
if (!res)
|
||||
pbx_builtin_setvar_helper(chan, tmp, tmp2);
|
||||
ast_verbose(VERBOSE_PREFIX_3 "User entered '%s'\n", tmp2);
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <asterisk/dsp.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Trivial Record Application";
|
||||
|
||||
@@ -29,19 +30,10 @@ static char *app = "Record";
|
||||
static char *synopsis = "Record to a file";
|
||||
|
||||
static char *descrip =
|
||||
" Record(filename:format|silence[|maxduration][|option])\n\n"
|
||||
"Records from the channel into a given filename. If the file exists it will\n"
|
||||
"be overwritten.\n"
|
||||
"- 'format' is the format of the file type to be recorded (wav, gsm, etc).\n"
|
||||
"- 'silence' is the number of seconds of silence to allow before returning.\n"
|
||||
"- 'maxduration' is the maximum recording duration in seconds. If missing\n"
|
||||
"or 0 there is no maximum.\n"
|
||||
"- 'option' may be 'skip' to return immediately if the line is not up,\n"
|
||||
"or 'noanswer' to attempt to record even if the line is not up.\n\n"
|
||||
"If filename contains '%d', these characters will be replaced with a number\n"
|
||||
"incremented by one each time the file is recorded. \n\n"
|
||||
"Formats: g723, g729, gsm, h263, ulaw, alaw, vox, wav, WAV\n\n"
|
||||
"User can press '#' to terminate the recording and continue to the next priority.\n\n"
|
||||
" Record(filename:extension|silence): Records from the channel into a given\n"
|
||||
"filename. If the file exists it will be overwritten. The 'extension'\n"
|
||||
"is the extension of the file type to be recorded (wav, gsm, etc).\n"
|
||||
"'silence' is the number of seconds of silence to allow before returning.\n"
|
||||
"Returns -1 when the user hangs up.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
@@ -56,7 +48,7 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
char fil[256];
|
||||
char tmp[256];
|
||||
char ext[10];
|
||||
char *vdata;
|
||||
char * vdata; /* Used so I don't have to typecast every use of *data */
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
@@ -70,128 +62,64 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
int silence = 0; /* amount of silence to allow */
|
||||
int gotsilence = 0; /* did we timeout for silence? */
|
||||
char silencestr[5];
|
||||
char durationstr[8];
|
||||
int maxduration = 0; /* max duration of recording */
|
||||
int gottimeout = 0; /* did we timeout for maxduration exceeded? */
|
||||
time_t timeout = 0;
|
||||
char option[16];
|
||||
int option_skip = 0;
|
||||
int option_noanswer = 0;
|
||||
int k = 0;
|
||||
int rfmt = 0;
|
||||
int flags;
|
||||
char *end=NULL;
|
||||
char *p=NULL;
|
||||
|
||||
|
||||
vdata = data; /* explained above */
|
||||
|
||||
/* The next few lines of code parse out the filename and header from the input string */
|
||||
if (!data) { /* no data implies no filename or anything is present */
|
||||
if (!vdata) { /* no data implies no filename or anything is present */
|
||||
ast_log(LOG_WARNING, "Record requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
vdata = ast_strdupa(data);
|
||||
|
||||
p = vdata;
|
||||
while(p && (p=strchr(p,':'))) {
|
||||
end=p;
|
||||
if(!strcasecmp(end,":end")) {
|
||||
*end='\0';
|
||||
end++;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
end=NULL;
|
||||
}
|
||||
|
||||
|
||||
for (; vdata[i] && (vdata[i] != ':') && (vdata[i] != '|'); i++ ) {
|
||||
if ((vdata[i] == '%') && (vdata[i+1] == 'd')) {
|
||||
percentflag = 1; /* the wildcard is used */
|
||||
}
|
||||
if (j < sizeof(fil) - 1)
|
||||
fil[j++] = vdata[i];
|
||||
|
||||
if (i == strlen(vdata) ) {
|
||||
ast_log(LOG_WARNING, "No extension found\n");
|
||||
return -1;
|
||||
}
|
||||
fil[i] = vdata[i];
|
||||
}
|
||||
fil[j] = '\0';
|
||||
fil[i++] = '\0';
|
||||
|
||||
if (vdata[i] != ':') {
|
||||
ast_log(LOG_WARNING, "No extension found\n");
|
||||
return -1;
|
||||
}
|
||||
i++;
|
||||
|
||||
j = 0;
|
||||
for (; vdata[i] && (vdata[i] != '|'); i++)
|
||||
if (j < sizeof(ext) - 1)
|
||||
ext[j++] = vdata[i];
|
||||
for (; j < 10 && i < strlen(data) && (vdata[i] != '|'); i++, j++)
|
||||
ext[j] = vdata[i];
|
||||
ext[j] = '\0';
|
||||
|
||||
if (vdata[i] == '|')
|
||||
i++;
|
||||
if (vdata[i] && (vdata[i] == '|')) i++;
|
||||
for (; vdata[i] && (vdata[i] != '|') && (k < 3) && i < strlen(data); i++, k++)
|
||||
silencestr[k] = vdata[i];
|
||||
silencestr[k] = '\0';
|
||||
|
||||
j = 0;
|
||||
for (; vdata[i] && (vdata[i] != '|'); i++)
|
||||
if (j < sizeof(silencestr) - 1)
|
||||
silencestr[j++] = vdata[i];
|
||||
silencestr[j] = '\0';
|
||||
|
||||
if (j > 0) {
|
||||
if (silencestr) {
|
||||
silence = atoi(silencestr);
|
||||
if (silence > 0)
|
||||
silence *= 1000;
|
||||
}
|
||||
|
||||
if (vdata[i] == '|')
|
||||
i++;
|
||||
|
||||
j = 0;
|
||||
for (; vdata[i] && (vdata[i] != '|'); i++)
|
||||
if (j < sizeof(durationstr) - 1)
|
||||
durationstr[j++] = vdata[i];
|
||||
durationstr[j] = '\0';
|
||||
|
||||
if (j > 0)
|
||||
maxduration = atoi(durationstr);
|
||||
|
||||
if (vdata[i] == '|')
|
||||
i++;
|
||||
|
||||
j = 0;
|
||||
for (; vdata[i] && (vdata[i] != '|'); i++)
|
||||
if (j < sizeof(option) - 1)
|
||||
option[j++] = vdata[i];
|
||||
option[j] = '\0';
|
||||
|
||||
if (!strcasecmp(option, "skip"))
|
||||
option_skip = 1;
|
||||
if (!strcasecmp(option, "noanswer"))
|
||||
option_noanswer = 1;
|
||||
|
||||
/* done parsing */
|
||||
|
||||
|
||||
|
||||
/* these are to allow the use of the %d in the config file for a wild card of sort to
|
||||
create a new file with the inputed name scheme */
|
||||
if (percentflag) {
|
||||
do {
|
||||
snprintf(tmp, sizeof(tmp), fil, count);
|
||||
snprintf(tmp, 256, fil, count);
|
||||
count++;
|
||||
} while ( ast_fileexists(tmp, ext, chan->language) != -1 );
|
||||
pbx_builtin_setvar_helper(chan, "RECORDED_FILE", tmp);
|
||||
} else
|
||||
strncpy(tmp, fil, sizeof(tmp)-1);
|
||||
strncpy(tmp, fil, 256-1);
|
||||
/* end of routine mentioned */
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
if (option_skip) {
|
||||
/* At the user's option, skip if the line is not up */
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
} else if (!option_noanswer) {
|
||||
/* Otherwise answer unless we're supposed to record while on-hook */
|
||||
res = ast_answer(chan);
|
||||
}
|
||||
res = ast_answer(chan); /* Shouldn't need this, but checking to see if channel is already answered
|
||||
* Theoretically asterisk should already have answered before running the app */
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
@@ -222,21 +150,10 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
ast_dsp_set_threshold(sildet, 256);
|
||||
}
|
||||
|
||||
|
||||
flags = end ? O_CREAT|O_APPEND|O_WRONLY : O_CREAT|O_TRUNC|O_WRONLY;
|
||||
s = ast_writefile( tmp, ext, NULL, flags , 0, 0644);
|
||||
|
||||
|
||||
s = ast_writefile( tmp, ext, NULL, O_CREAT|O_TRUNC|O_WRONLY , 0, 0644);
|
||||
|
||||
if (s) {
|
||||
if (maxduration > 0)
|
||||
timeout = time(NULL) + (time_t)maxduration;
|
||||
|
||||
while (ast_waitfor(chan, -1) > -1) {
|
||||
if (maxduration > 0 && time(NULL) > timeout) {
|
||||
gottimeout = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
res = -1;
|
||||
@@ -289,7 +206,7 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
if (gotsilence) {
|
||||
ast_stream_rewind(s, silence-1000);
|
||||
ast_truncstream(s);
|
||||
} else if (!gottimeout) {
|
||||
} else {
|
||||
/* Strip off the last 1/4 second of it */
|
||||
ast_stream_rewind(s, 250);
|
||||
ast_truncstream(s);
|
||||
@@ -301,7 +218,7 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
if ((silence > 0) && rfmt) {
|
||||
if (silence > 0) {
|
||||
res = ast_set_read_format(chan, rfmt);
|
||||
if (res)
|
||||
ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
|
||||
|
||||
3737
apps/app_rpt.c
3737
apps/app_rpt.c
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,6 @@
|
||||
static char *tdesc = "Say time";
|
||||
|
||||
static char *app_sayunixtime = "SayUnixTime";
|
||||
static char *app_datetime = "DateTime";
|
||||
|
||||
static char *sayunixtime_synopsis = "Says a specified time in a custom format";
|
||||
|
||||
@@ -40,15 +39,6 @@ static char *sayunixtime_descrip =
|
||||
" format: a format the time is to be said in. See voicemail.conf.\n"
|
||||
" defaults to \"ABdY 'digits/at' IMp\"\n"
|
||||
" Returns 0 or -1 on hangup.\n";
|
||||
static char *datetime_descrip =
|
||||
"DateTime([unixtime][|[timezone][|format]])\n"
|
||||
" unixtime: time, in seconds since Jan 1, 1970. May be negative.\n"
|
||||
" defaults to now.\n"
|
||||
" timezone: timezone, see /usr/share/zoneinfo for a list.\n"
|
||||
" defaults to machine default.\n"
|
||||
" format: a format the time is to be said in. See voicemail.conf.\n"
|
||||
" defaults to \"ABdY 'digits/at' IMp\"\n"
|
||||
" Returns 0 or -1 on hangup.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -104,23 +94,13 @@ static int sayunixtime_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
res = ast_unregister_application(app_sayunixtime);
|
||||
if (! res)
|
||||
return ast_unregister_application(app_datetime);
|
||||
else
|
||||
return res;
|
||||
return ast_unregister_application(app_sayunixtime);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
res = ast_register_application(app_sayunixtime, sayunixtime_exec, sayunixtime_synopsis, sayunixtime_descrip);
|
||||
if (! res)
|
||||
return ast_register_application(app_datetime, sayunixtime_exec, sayunixtime_synopsis, datetime_descrip);
|
||||
else
|
||||
return res;
|
||||
return ast_register_application(app_sayunixtime, sayunixtime_exec, sayunixtime_synopsis, sayunixtime_descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
|
||||
@@ -19,10 +19,9 @@
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Send DTMF digits Application";
|
||||
|
||||
@@ -31,9 +30,8 @@ static char *app = "SendDTMF";
|
||||
static char *synopsis = "Sends arbitrary DTMF digits";
|
||||
|
||||
static char *descrip =
|
||||
" SendDTMF(digits): Sends DTMF digits on a channel. \n"
|
||||
" Accepted digits: 0-9, *#abcd\n"
|
||||
" Returns 0 on success or -1 on a hangup.\n";
|
||||
" SendDTMF(digits): Sends DTMF digits on a channel. Returns 0 on success"
|
||||
"or -1 on a hangup.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -44,13 +42,30 @@ static int senddtmf_exec(struct ast_channel *chan, void *data)
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
char *digits = data;
|
||||
|
||||
if (!digits || ast_strlen_zero(digits)) {
|
||||
ast_log(LOG_WARNING, "SendDTMF requires an argument (digits or *#aAbBcCdD)\n");
|
||||
struct ast_frame f;
|
||||
int x;
|
||||
if (!digits || !strlen(digits)) {
|
||||
ast_log(LOG_WARNING, "SendDTMF requires an argument (digits)\n");
|
||||
return -1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
res = ast_dtmf_stream(chan,NULL,digits,250);
|
||||
for (x=0;x<strlen(digits);x++) {
|
||||
memset(&f, 0, sizeof(f));
|
||||
f.frametype = AST_FRAME_DTMF;
|
||||
f.subclass = digits[x];
|
||||
f.src = "app_senddtmf";
|
||||
res = ast_write(chan, &f);
|
||||
if (res)
|
||||
break;
|
||||
/* Wait 250ms */
|
||||
res = ast_safe_sleep(chan, 250);
|
||||
if (res)
|
||||
break;
|
||||
}
|
||||
if (!res)
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Sent digit string '%s' on %s\n", digits, chan->name);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* App to transmit a text message
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/channel_pvt.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/image.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static char *tdesc = "Send Text Applications";
|
||||
|
||||
static char *app = "SendText";
|
||||
|
||||
static char *synopsis = "Send a Text Message";
|
||||
|
||||
static char *descrip =
|
||||
" SendText(text): Sends text to client. If the client\n"
|
||||
"does not support text transport, and there exists a step with\n"
|
||||
"priority n + 101, then execution will continue at that step.\n"
|
||||
"Otherwise, execution will continue at the next priority level.\n"
|
||||
"SendText only returns 0 if the text was sent correctly or if\n"
|
||||
"the channel does not support text transport, and -1 otherwise.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int sendtext_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
if (!data || !strlen((char *)data)) {
|
||||
ast_log(LOG_WARNING, "SendText requires an argument (text)\n");
|
||||
return -1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
ast_mutex_lock(&chan->lock);
|
||||
if (!chan->pvt->send_text) {
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
/* Does not support transport */
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
res = ast_sendtext(chan, (char *)data);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, sendtext_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -19,82 +19,9 @@
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/image.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static char *app2 = "SetCallerPres";
|
||||
|
||||
static char *synopsis2 = "Set CallerID Presentation";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static struct {
|
||||
int val;
|
||||
char *name;
|
||||
} preses[] = {
|
||||
{ AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened" },
|
||||
{ AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen" },
|
||||
{ AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen" },
|
||||
{ AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed" },
|
||||
{ AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED , "prohib_not_screened" },
|
||||
{ AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen" },
|
||||
{ AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen" },
|
||||
{ AST_PRES_PROHIB_NETWORK_NUMBER, "prohib" },
|
||||
{ AST_PRES_NUMBER_NOT_AVAILABLE, "unavailable" },
|
||||
};
|
||||
|
||||
static char *descrip2 =
|
||||
" SetCallerPres(presentation): Set Caller*ID presentation on\n"
|
||||
"a call to a new value. Sets ANI as well if a flag is used.\n"
|
||||
"Always returns 0. Valid presentations are:\n"
|
||||
"\n"
|
||||
" allowed_not_screened : Presentation Allowed, Not Screened\n"
|
||||
" allowed_passed_screen : Presentation Allowed, Passed Screen\n"
|
||||
" allowed_failed_screen : Presentation Allowed, Failed Screen\n"
|
||||
" allowed : Presentation Allowed, Network Number\n"
|
||||
" prohib_not_screened : Presentation Prohibited, Not Screened\n"
|
||||
" prohib_passed_screen : Presentation Prohibited, Passed Screen\n"
|
||||
" prohib_failed_screen : Presentation Prohibited, Failed Screen\n"
|
||||
" prohib : Presentation Prohibited, Network Number\n"
|
||||
" unavailable : Number Unavailable\n"
|
||||
"\n"
|
||||
;
|
||||
|
||||
static int setcallerid_pres_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
char tmp[256] = "";
|
||||
struct localuser *u;
|
||||
int x;
|
||||
char *opts;
|
||||
int pres = -1;
|
||||
if (data)
|
||||
strncpy(tmp, (char *)data, sizeof(tmp) - 1);
|
||||
opts = strchr(tmp, '|');
|
||||
if (opts) {
|
||||
*opts = '\0';
|
||||
opts++;
|
||||
}
|
||||
for (x=0;x<sizeof(preses) / sizeof(preses[0]);x++) {
|
||||
if (!strcasecmp(preses[x].name, tmp)) {
|
||||
pres = preses[x].val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pres < 0) {
|
||||
ast_log(LOG_WARNING, "'%s' is not a valid presentation (see 'show application SetCallerPres')\n", tmp);
|
||||
return 0;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
chan->callingpres = pres;
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Set CallerID Application";
|
||||
|
||||
@@ -106,6 +33,10 @@ static char *descrip =
|
||||
" SetCallerID(clid[|a]): Set Caller*ID on a call to a new\n"
|
||||
"value. Sets ANI as well if a flag is used. Always returns 0\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int setcallerid_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
@@ -131,13 +62,11 @@ static int setcallerid_exec(struct ast_channel *chan, void *data)
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
ast_unregister_application(app2);
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
ast_register_application(app2, setcallerid_pres_exec, synopsis2, descrip2);
|
||||
return ast_register_application(app, setcallerid_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,9 +17,7 @@
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/config.h>
|
||||
#include <asterisk/manager.h>
|
||||
#include <asterisk/utils.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -61,41 +59,6 @@ STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int action_setcdruserfield(struct mansession *s, struct message *m)
|
||||
{
|
||||
struct ast_channel *c = NULL;
|
||||
char *userfield = astman_get_header(m, "UserField");
|
||||
char *channel = astman_get_header(m, "Channel");
|
||||
char *append = astman_get_header(m, "Append");
|
||||
|
||||
if (ast_strlen_zero(channel)) {
|
||||
astman_send_error(s, m, "No Channel specified");
|
||||
return 0;
|
||||
}
|
||||
if (ast_strlen_zero(userfield)) {
|
||||
astman_send_error(s, m, "No UserField specified");
|
||||
return 0;
|
||||
}
|
||||
c = ast_channel_walk_locked(NULL);
|
||||
while (c) {
|
||||
if (!strcasecmp(c->name, channel))
|
||||
break;
|
||||
ast_mutex_unlock(&c->lock);
|
||||
c = ast_channel_walk_locked(c);
|
||||
}
|
||||
if (!c) {
|
||||
astman_send_error(s, m, "No such channel");
|
||||
return 0;
|
||||
}
|
||||
if (ast_true(append))
|
||||
ast_cdr_appenduserfield(c, userfield);
|
||||
else
|
||||
ast_cdr_setuserfield(c, userfield);
|
||||
ast_mutex_unlock(&c->lock);
|
||||
astman_send_ack(s, m, "CDR Userfield Set");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setcdruserfield_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct localuser *u;
|
||||
@@ -134,7 +97,6 @@ int unload_module(void)
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
res = ast_unregister_application(setcdruserfield_app);
|
||||
res |= ast_unregister_application(appendcdruserfield_app);
|
||||
ast_manager_unregister("SetCDRUserField");
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -143,7 +105,7 @@ int load_module(void)
|
||||
int res;
|
||||
res = ast_register_application(setcdruserfield_app, setcdruserfield_exec, setcdruserfield_synopsis, setcdruserfield_descrip);
|
||||
res |= ast_register_application(appendcdruserfield_app, appendcdruserfield_exec, appendcdruserfield_synopsis, appendcdruserfield_descrip);
|
||||
ast_manager_register("SetCDRUserField", EVENT_FLAG_CALL, action_setcdruserfield, "Set the CDR UserField");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/image.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Set CallerID Name";
|
||||
|
||||
@@ -63,17 +63,17 @@ static int setcallerid_exec(struct ast_channel *chan, void *data)
|
||||
strncpy(oldcid, chan->callerid, sizeof(oldcid) - 1);
|
||||
ast_callerid_parse(oldcid, &n, &l);
|
||||
n = tmp;
|
||||
if (!ast_strlen_zero(n)) {
|
||||
if (l && !ast_strlen_zero(l))
|
||||
if (strlen(n)) {
|
||||
if (l && strlen(l))
|
||||
snprintf(newcid, sizeof(newcid), "\"%s\" <%s>", n, l);
|
||||
else
|
||||
strncpy(newcid, tmp, sizeof(newcid) - 1);
|
||||
} else if (l && !ast_strlen_zero(l)) {
|
||||
} else if (l && strlen(l)) {
|
||||
strncpy(newcid, l, sizeof(newcid) - 1);
|
||||
}
|
||||
} else
|
||||
strncpy(newcid, tmp, sizeof(newcid) - 1);
|
||||
ast_set_callerid(chan, !ast_strlen_zero(newcid) ? newcid : NULL, anitoo);
|
||||
strncpy(newcid, tmp, sizeof(newcid));
|
||||
ast_set_callerid(chan, strlen(newcid) ? newcid : NULL, anitoo);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/image.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Set CallerID Number";
|
||||
|
||||
@@ -64,17 +64,17 @@ static int setcallerid_exec(struct ast_channel *chan, void *data)
|
||||
strncpy(oldcid, chan->callerid, sizeof(oldcid) - 1);
|
||||
ast_callerid_parse(oldcid, &n, &l);
|
||||
l = tmp;
|
||||
if (!ast_strlen_zero(l)) {
|
||||
if (n && !ast_strlen_zero(n))
|
||||
if (strlen(l)) {
|
||||
if (n && strlen(n))
|
||||
snprintf(newcid, sizeof(newcid), "\"%s\" <%s>", n, l);
|
||||
else
|
||||
strncpy(newcid, tmp, sizeof(newcid) - 1);
|
||||
} else if (n && !ast_strlen_zero(n)) {
|
||||
} else if (n && strlen(n)) {
|
||||
strncpy(newcid, n, sizeof(newcid) - 1);
|
||||
}
|
||||
} else
|
||||
strncpy(newcid, tmp, sizeof(newcid) - 1);
|
||||
ast_set_callerid(chan, !ast_strlen_zero(newcid) ? newcid : NULL, anitoo);
|
||||
strncpy(newcid, tmp, sizeof(newcid));
|
||||
ast_set_callerid(chan, strlen(newcid) ? newcid : NULL, anitoo);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Trivial skeleton Application";
|
||||
static char *app = "skel";
|
||||
|
||||
1235
apps/app_sms.c
1235
apps/app_sms.c
File diff suppressed because it is too large
Load Diff
@@ -17,12 +17,14 @@
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *synopsis = "Soft Hangup Application";
|
||||
|
||||
static char *tdesc = "Hangs up the requested channel";
|
||||
@@ -45,15 +47,13 @@ static int softhangup_exec(struct ast_channel *chan, void *data)
|
||||
return 0;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
c = ast_channel_walk_locked(NULL);
|
||||
c = ast_channel_walk(NULL);
|
||||
while (c) {
|
||||
if (!strcasecmp(c->name, data)) {
|
||||
ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
|
||||
ast_mutex_unlock(&c->lock);
|
||||
break;
|
||||
}
|
||||
ast_mutex_unlock(&c->lock);
|
||||
c = ast_channel_walk_locked(c);
|
||||
c = ast_channel_walk(c);
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* Copyright (C) 2002, Christos Ricudis
|
||||
*
|
||||
* Christos Ricudis <ricudis@itc.auth.gr>
|
||||
* Christos Ricudis <ricudis@paiko.gr>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
@@ -26,9 +26,10 @@
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include "libpq-fe.h"
|
||||
|
||||
#define EXTRA_LOG 0
|
||||
|
||||
|
||||
|
||||
static char *tdesc = "Simple PostgreSQL Interface";
|
||||
@@ -38,67 +39,57 @@ static char *app = "PGSQL";
|
||||
static char *synopsis = "Do several SQLy things";
|
||||
|
||||
static char *descrip =
|
||||
"PGSQL(): Do several SQLy things\n"
|
||||
"Syntax:\n"
|
||||
" PGSQL(Connect var option-string)\n"
|
||||
" Connects to a database. Option string contains standard PostgreSQL\n"
|
||||
" parameters like host=, dbname=, user=. Connection identifer returned\n"
|
||||
" in ${var}\n"
|
||||
" PGSQL(Query var ${connection_identifier} query-string)\n"
|
||||
" Executes standard SQL query contained in query-string using established\n"
|
||||
" connection identified by ${connection_identifier}. Reseult of query is\n"
|
||||
" is stored in ${var}.\n"
|
||||
" PGSQL(Fetch statusvar ${result_identifier} var1 var2 ... varn)\n"
|
||||
" Fetches a single row from a result set contained in ${result_identifier}.\n"
|
||||
" Assigns returned fields to ${var1} ... ${varn}. ${statusvar} is set TRUE\n"
|
||||
" if additional rows exist in reseult set.\n"
|
||||
" PGSQL(Clear ${result_identifier})\n"
|
||||
" Frees memory and datastructures associated with result set.\n"
|
||||
" PGSQL(Disconnect ${connection_identifier})\n"
|
||||
" Disconnects from named connection to PostgreSQL.\n" ;
|
||||
" PGSQL(): Do several SQLy things\n";
|
||||
|
||||
/*
|
||||
|
||||
Syntax of SQL commands :
|
||||
|
||||
Connect var option-string
|
||||
Connect #var option-string
|
||||
|
||||
Connects to a database using the option-string and stores the
|
||||
connection identifier in ${var}
|
||||
connection identifier in $var
|
||||
|
||||
|
||||
Query var ${connection_identifier} query-string
|
||||
Query var connection-identifier query-string
|
||||
|
||||
Submits query-string to database backend and stores the result
|
||||
identifier in ${var}
|
||||
|
||||
|
||||
Fetch statusvar ${result_identifier} var1 var2 var3 ... varn
|
||||
Fetch statusvar result-identifier var1 var2 var3 ... varn
|
||||
|
||||
Fetches a row from the query and stores end-of-table status in
|
||||
${statusvar} and columns in ${var1}..${varn}
|
||||
|
||||
|
||||
Clear ${result_identifier}
|
||||
Clear result-identifier
|
||||
|
||||
Clears data structures associated with ${result_identifier}
|
||||
Clears data structures associated with result-identifier
|
||||
|
||||
|
||||
Disconnect ${connection_identifier}
|
||||
Disconnect connection-identifier
|
||||
|
||||
Disconnects from named connection
|
||||
|
||||
|
||||
EXAMPLES OF USE :
|
||||
|
||||
exten => s,2,PGSQL(Connect connid host=localhost user=asterisk dbname=credit)
|
||||
exten => s,3,PGSQL(Query resultid ${connid} SELECT username,credit FROM credit WHERE callerid=${CALLERIDNUM})
|
||||
exten => s,4,PGSQL(Fetch fetchid ${resultid} datavar1 datavar2)
|
||||
exten => s,5,GotoIf(${fetchid}?6:8)
|
||||
exten => s,6,Festival("User ${datavar1} currently has credit balance of ${datavar2} dollars.")
|
||||
exten => s,7,Goto(s,4)
|
||||
exten => s,8,PGSQL(Clear ${resultid})
|
||||
exten => s,9,PGSQL(Disconnect ${connid})
|
||||
(
|
||||
$2 = Connection Identifier
|
||||
$3 = Result Identifier
|
||||
$4 = Fetch Status Identifier (0 = no more rows)
|
||||
$5, $6 = Data variables
|
||||
)
|
||||
|
||||
exten => s,2,PGSQL,"Connect connid host=localhost user=asterisk dbname=credit";
|
||||
exten => s,3,PGSQL,"Query resultid ${connid} SELECT username,credit FROM credit WHERE callerid=${callerid}";
|
||||
exten => s,4,PGSQL,"Fetch fetchid ${resultid} datavar1 datavar2";
|
||||
exten => s,5,GotoIf,"${fetchid}=1?s|6:s|8";
|
||||
exten => s,6,blablabla ${datavar1} ${datavar2} (does blablabla, datavar1 = username, datavar2 = credit);
|
||||
exten => s,7,Goto,s|4
|
||||
exten => s,8,PGSQL,"Clear ${resultid}";
|
||||
exten => s,9,PGSQL,"Disconnect ${connid}";
|
||||
|
||||
*/
|
||||
|
||||
@@ -210,8 +201,8 @@ static int del_identifier(int identifier,int identifier_type) {
|
||||
|
||||
static int aPGSQL_connect(struct ast_channel *chan, void *data) {
|
||||
|
||||
char *s1;
|
||||
char s[100] = "";
|
||||
char *s1,*s4;
|
||||
char s[100];
|
||||
char *optionstring;
|
||||
char *var;
|
||||
int l;
|
||||
@@ -224,7 +215,7 @@ static int aPGSQL_connect(struct ast_channel *chan, void *data) {
|
||||
res=0;
|
||||
l=strlen(data)+2;
|
||||
s1=malloc(l);
|
||||
strncpy(s1, data, l -1);
|
||||
strncpy(s1,data,l);
|
||||
stringp=s1;
|
||||
strsep(&stringp," "); // eat the first token, we already know it :P
|
||||
var=strsep(&stringp," ");
|
||||
@@ -238,7 +229,8 @@ static int aPGSQL_connect(struct ast_channel *chan, void *data) {
|
||||
} else {
|
||||
ast_log(LOG_WARNING,"adding identifier\n");
|
||||
id=add_identifier(AST_PGSQL_ID_CONNID,karoto);
|
||||
snprintf(s, sizeof(s), "%d", id);
|
||||
s4=&s[0];
|
||||
sprintf(s4,"%d",id);
|
||||
pbx_builtin_setvar_helper(chan,var,s);
|
||||
}
|
||||
|
||||
@@ -248,9 +240,8 @@ static int aPGSQL_connect(struct ast_channel *chan, void *data) {
|
||||
|
||||
static int aPGSQL_query(struct ast_channel *chan, void *data) {
|
||||
|
||||
|
||||
char *s1,*s2,*s3,*s4;
|
||||
char s[100] = "";
|
||||
char *s1,*s2,*s3,*s4,*s5;
|
||||
char s[100];
|
||||
char *querystring;
|
||||
char *var;
|
||||
int l;
|
||||
@@ -265,7 +256,7 @@ static int aPGSQL_query(struct ast_channel *chan, void *data) {
|
||||
l=strlen(data)+2;
|
||||
s1=malloc(l);
|
||||
s2=malloc(l);
|
||||
strncpy(s1, data, l - 1);
|
||||
strcpy(s1,data);
|
||||
stringp=s1;
|
||||
strsep(&stringp," "); // eat the first token, we already know it :P
|
||||
s3=strsep(&stringp," ");
|
||||
@@ -294,21 +285,21 @@ static int aPGSQL_query(struct ast_channel *chan, void *data) {
|
||||
}
|
||||
nres=PQnfields(PGSQLres);
|
||||
id1=add_identifier(AST_PGSQL_ID_RESID,PGSQLres);
|
||||
snprintf(s, sizeof(s), "%d", id1);
|
||||
s5=&s[0];
|
||||
sprintf(s5,"%d",id1);
|
||||
pbx_builtin_setvar_helper(chan,var,s);
|
||||
break;
|
||||
}
|
||||
|
||||
free(s1);
|
||||
free(s2);
|
||||
|
||||
return(res);
|
||||
}
|
||||
|
||||
|
||||
static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
|
||||
|
||||
char *s1,*s2,*fetchid_var,*s4,*s5,*s6,*s7;
|
||||
char *s1,*s2,*s3,*s4,*s5,*s6,*s7;
|
||||
char s[100];
|
||||
char *var;
|
||||
int l;
|
||||
@@ -328,16 +319,16 @@ static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
|
||||
s7=NULL;
|
||||
s1=malloc(l);
|
||||
s2=malloc(l);
|
||||
strncpy(s1, data, l - 1);
|
||||
strcpy(s1,data);
|
||||
stringp=s1;
|
||||
strsep(&stringp," "); // eat the first token, we already know it :P
|
||||
fetchid_var=strsep(&stringp," ");
|
||||
s3=strsep(&stringp," ");
|
||||
while (1) { // ugly trick to make branches with break;
|
||||
var=fetchid_var; // fetchid
|
||||
var=s3; // fetchid
|
||||
fnd=0;
|
||||
|
||||
AST_LIST_TRAVERSE(headp,variables,entries) {
|
||||
if (strncasecmp(ast_var_name(variables),fetchid_var,strlen(fetchid_var))==0) {
|
||||
if (strncasecmp(ast_var_name(variables),s3,strlen(s3))==0) {
|
||||
s7=ast_var_value(variables);
|
||||
fnd=1;
|
||||
break;
|
||||
@@ -346,7 +337,7 @@ static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
|
||||
|
||||
if (fnd==0) {
|
||||
s7="0";
|
||||
pbx_builtin_setvar_helper(chan,fetchid_var,s7);
|
||||
pbx_builtin_setvar_helper(chan,s3,s7);
|
||||
}
|
||||
|
||||
s4=strsep(&stringp," ");
|
||||
@@ -358,14 +349,12 @@ static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
|
||||
}
|
||||
id=atoi(s7); //fetchid
|
||||
if ((lalares=find_identifier(id,AST_PGSQL_ID_FETCHID))==NULL) {
|
||||
i=0; // fetching the very first row
|
||||
i=0;
|
||||
} else {
|
||||
i=*lalares;
|
||||
free(lalares);
|
||||
del_identifier(id,AST_PGSQL_ID_FETCHID); // will re-add it a bit later
|
||||
del_identifier(id,AST_PGSQL_ID_FETCHID);
|
||||
}
|
||||
|
||||
if (i<PQntuples(PGSQLres)) {
|
||||
nres=PQnfields(PGSQLres);
|
||||
ast_log(LOG_WARNING,"ast_PGSQL_fetch : nres = %d i = %d ;\n",nres,i);
|
||||
for (j=0;j<nres;j++) {
|
||||
@@ -374,6 +363,7 @@ static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
|
||||
ast_log(LOG_WARNING,"ast_PGSQL_fetch : More tuples (%d) than variables (%d)\n",nres,j);
|
||||
break;
|
||||
}
|
||||
|
||||
s6=PQgetvalue(PGSQLres,i,j);
|
||||
if (s6==NULL) {
|
||||
ast_log(LOG_WARNING,"PWgetvalue(res,%d,%d) returned NULL in ast_PGSQL_fetch\n",i,j);
|
||||
@@ -382,16 +372,18 @@ static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
|
||||
ast_log(LOG_WARNING,"===setting variable '%s' to '%s'\n",s5,s6);
|
||||
pbx_builtin_setvar_helper(chan,s5,s6);
|
||||
}
|
||||
i++;
|
||||
if (i<PQntuples(PGSQLres)) {
|
||||
lalares=malloc(sizeof(int));
|
||||
*lalares = ++i; // advance to the next row
|
||||
id1 = add_identifier(AST_PGSQL_ID_FETCHID,lalares);
|
||||
*lalares=i;
|
||||
id1=add_identifier(AST_PGSQL_ID_FETCHID,lalares);
|
||||
} else {
|
||||
ast_log(LOG_WARNING,"ast_PGSQL_fetch : EOF\n");
|
||||
id1 = 0; // no more rows
|
||||
id1=0;
|
||||
}
|
||||
snprintf(s, sizeof(s), "%d", id1);
|
||||
ast_log(LOG_WARNING,"Setting var '%s' to value '%s'\n",fetchid_var,s);
|
||||
pbx_builtin_setvar_helper(chan,fetchid_var,s);
|
||||
s5=&s[0];
|
||||
sprintf(s5,"%d",id1);
|
||||
ast_log(LOG_WARNING,"Setting var '%s' to value '%s'\n",s3,s);
|
||||
pbx_builtin_setvar_helper(chan,s3,s);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -411,7 +403,7 @@ static int aPGSQL_reset(struct ast_channel *chan, void *data) {
|
||||
|
||||
l=strlen(data)+2;
|
||||
s1=malloc(l);
|
||||
strncpy(s1, data, l - 1);
|
||||
strcpy(s1,data);
|
||||
stringp=s1;
|
||||
strsep(&stringp," "); // eat the first token, we already know it :P
|
||||
s3=strsep(&stringp," ");
|
||||
@@ -437,7 +429,7 @@ static int aPGSQL_clear(struct ast_channel *chan, void *data) {
|
||||
|
||||
l=strlen(data)+2;
|
||||
s1=malloc(l);
|
||||
strncpy(s1, data, l - 1);
|
||||
strcpy(s1,data);
|
||||
stringp=s1;
|
||||
strsep(&stringp," "); // eat the first token, we already know it :P
|
||||
s3=strsep(&stringp," ");
|
||||
@@ -467,7 +459,7 @@ static int aPGSQL_disconnect(struct ast_channel *chan, void *data) {
|
||||
|
||||
l=strlen(data)+2;
|
||||
s1=malloc(l);
|
||||
strncpy(s1, data, l - 1);
|
||||
strcpy(s1,data);
|
||||
stringp=s1;
|
||||
strsep(&stringp," "); // eat the first token, we already know it :P
|
||||
s3=strsep(&stringp," ");
|
||||
@@ -495,10 +487,6 @@ static int PGSQL_exec(struct ast_channel *chan, void *data)
|
||||
struct localuser *u;
|
||||
int result;
|
||||
|
||||
#if EXTRA_LOG
|
||||
printf("PRSQL_exec: data=%s\n",(char*)data);
|
||||
#endif
|
||||
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "APP_PGSQL requires an argument (see manual)\n");
|
||||
return -1;
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "Strip trailing digits";
|
||||
|
||||
static char *descrip =
|
||||
@@ -45,27 +47,16 @@ LOCAL_USER_DECL;
|
||||
|
||||
static int striplsd_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
char newexten[AST_MAX_EXTENSION] = "";
|
||||
int maxbytes = 0;
|
||||
int stripcount = 0;
|
||||
int extlen = strlen(chan->exten);
|
||||
|
||||
maxbytes = sizeof(newexten) - 1;
|
||||
if (data) {
|
||||
stripcount = atoi(data);
|
||||
}
|
||||
if (!stripcount) {
|
||||
ast_log(LOG_DEBUG, "Ignoring, since number of digits to strip is 0\n");
|
||||
return 0;
|
||||
}
|
||||
if (extlen > stripcount) {
|
||||
if (extlen - stripcount <= maxbytes) {
|
||||
maxbytes = extlen - stripcount;
|
||||
}
|
||||
strncpy(newexten, chan->exten, maxbytes);
|
||||
}
|
||||
strncpy(chan->exten, newexten, sizeof(chan->exten)-1);
|
||||
return 0;
|
||||
char newexten[AST_MAX_EXTENSION] = "";
|
||||
if (!data || !atoi(data)) {
|
||||
ast_log(LOG_DEBUG, "Ignoring, since number of digits to strip is 0\n");
|
||||
return 0;
|
||||
}
|
||||
if (strlen(chan->exten) > atoi(data)) {
|
||||
strncpy(newexten, chan->exten, strlen(chan->exten)-atoi(data));
|
||||
}
|
||||
strncpy(chan->exten, newexten, sizeof(chan->exten)-1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
|
||||
@@ -18,17 +18,17 @@
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static char *tdesc = "(Deprecated) Save substring digits in a given variable";
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "Save substring digits in a given variable";
|
||||
|
||||
static char *descrip =
|
||||
" (Deprecated, use ${variable:a:b} instead)\n"
|
||||
"\n"
|
||||
" SubString(variable=string_of_digits|count1|count2): Assigns the substring\n"
|
||||
"of string_of_digits to a given variable. Parameter count1 may be positive\n"
|
||||
"or negative. If it's positive then we skip the first count1 digits from the\n"
|
||||
@@ -48,7 +48,7 @@ static char *descrip =
|
||||
|
||||
static char *app = "SubString";
|
||||
|
||||
static char *synopsis = "(Deprecated) Save substring digits in a given variable";
|
||||
static char *synopsis = "Save substring digits in a given variable";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -59,10 +59,9 @@ static int substring_exec(struct ast_channel *chan, void *data)
|
||||
char newexten[AST_MAX_EXTENSION] = "";
|
||||
char *count1, *count2;
|
||||
char *first, *second, *stringp;
|
||||
|
||||
stringp=alloca(strlen(data)+1);
|
||||
ast_log(LOG_WARNING, "The use of Substring application is deprecated. Please use ${variable:a:b} instead\n");
|
||||
strncpy(stringp,data,strlen(data));
|
||||
strncpy(stringp,data,strlen(data)+1);
|
||||
if (strchr(stringp,'|')&&strchr(stringp,'=')) {
|
||||
int icount1,icount2;
|
||||
first=strsep(&stringp,"=");
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
*
|
||||
* Execute arbitrary system commands
|
||||
*
|
||||
* Copyright (C) 1999-2004, Digium, Inc.
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
@@ -17,23 +17,20 @@
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "Generic System() application";
|
||||
|
||||
static char *app = "System";
|
||||
|
||||
static char *app2 = "TrySystem";
|
||||
|
||||
static char *synopsis = "Execute a system command";
|
||||
|
||||
static char *synopsis2 = "Try executing a system command";
|
||||
|
||||
static char *descrip =
|
||||
" System(command): Executes a command by using system(). Returns -1 on\n"
|
||||
"failure to execute the specified command. If the command itself executes\n"
|
||||
@@ -41,37 +38,28 @@ static char *descrip =
|
||||
"priority of the current instance, then the channel will be setup to\n"
|
||||
"continue at that priority level. Otherwise, System returns 0.\n";
|
||||
|
||||
static char *descrip2 =
|
||||
" TrySystem(command): Executes a command by using system(). Returns 0\n"
|
||||
"on any situation. If the command itself executes but is in error, and if\n"
|
||||
"there exists a priority n + 101, where 'n' is the priority of the current\n"
|
||||
"instance, then the channel will be setup to continue at that\n"
|
||||
"priority level. Otherwise, System returns 0.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int system_exec_helper(struct ast_channel *chan, void *data, int failmode)
|
||||
static int system_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "System requires an argument(command)\n");
|
||||
return failmode;
|
||||
return -1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
/* Do our thing here */
|
||||
res = ast_safe_system((char *)data);
|
||||
if ((res < 0) && (errno != ECHILD)) {
|
||||
res = system((char *)data);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data);
|
||||
res = failmode;
|
||||
res = -1;
|
||||
} else if (res == 127) {
|
||||
ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data);
|
||||
res = failmode;
|
||||
res = -1;
|
||||
} else {
|
||||
if (res < 0)
|
||||
res = 0;
|
||||
if (res && ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority+=100;
|
||||
res = 0;
|
||||
@@ -80,26 +68,14 @@ static int system_exec_helper(struct ast_channel *chan, void *data, int failmode
|
||||
return res;
|
||||
}
|
||||
|
||||
static int system_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
return system_exec_helper(chan, data, -1);
|
||||
}
|
||||
|
||||
static int trysystem_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
return system_exec_helper(chan, data, 0);
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
ast_unregister_application(app2);
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
ast_register_application(app2, trysystem_exec, synopsis2, descrip2);
|
||||
return ast_register_application(app, system_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,218 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Playback a file with audio detect
|
||||
*
|
||||
* Copyright (C) 2004, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/dsp.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static char *tdesc = "Playback with Talk Detection";
|
||||
|
||||
static char *app = "BackgroundDetect";
|
||||
|
||||
static char *synopsis = "Background a file with talk detect";
|
||||
|
||||
static char *descrip =
|
||||
" BackgroundDetect(filename[|sil[|min|[max]]]): Plays back a given\n"
|
||||
"filename, waiting for interruption from a given digit (the digit must\n"
|
||||
"start the beginning of a valid extension, or it will be ignored).\n"
|
||||
"During the playback of the file, audio is monitored in the receive\n"
|
||||
"direction, and if a period of non-silence which is greater than 'min' ms\n"
|
||||
"yet less than 'max' ms is followed by silence for at least 'sil' ms then\n"
|
||||
"the audio playback is aborted and processing jumps to the 'talk' extension\n"
|
||||
"if available. If unspecified, sil, min, and max default to 1000, 100, and\n"
|
||||
"infinity respectively. Returns -1 on hangup, and 0 on successful playback\n"
|
||||
"completion with no exit conditions.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int background_detect_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
char tmp[256];
|
||||
char *options;
|
||||
char *stringp;
|
||||
struct ast_frame *fr;
|
||||
int notsilent=0;
|
||||
struct timeval start = { 0, 0}, end = {0, 0};
|
||||
int sil = 1000;
|
||||
int min = 100;
|
||||
int max = -1;
|
||||
int x;
|
||||
int origrformat=0;
|
||||
struct ast_dsp *dsp;
|
||||
if (!data || ast_strlen_zero((char *)data)) {
|
||||
ast_log(LOG_WARNING, "BackgroundDetect requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(tmp, (char *)data, sizeof(tmp)-1);
|
||||
stringp=tmp;
|
||||
strsep(&stringp, "|");
|
||||
options = strsep(&stringp, "|");
|
||||
if (options) {
|
||||
if ((sscanf(options, "%d", &x) == 1) && (x > 0))
|
||||
sil = x;
|
||||
options = strsep(&stringp, "|");
|
||||
if (options) {
|
||||
if ((sscanf(options, "%d", &x) == 1) && (x > 0))
|
||||
min = x;
|
||||
options = strsep(&stringp, "|");
|
||||
if (options) {
|
||||
if ((sscanf(options, "%d", &x) == 1) && (x > 0))
|
||||
max = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_log(LOG_DEBUG, "Preparing detect of '%s', sil=%d,min=%d,max=%d\n",
|
||||
tmp, sil, min, max);
|
||||
LOCAL_USER_ADD(u);
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
/* Otherwise answer unless we're supposed to send this while on-hook */
|
||||
res = ast_answer(chan);
|
||||
}
|
||||
if (!res) {
|
||||
origrformat = chan->readformat;
|
||||
if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)))
|
||||
ast_log(LOG_WARNING, "Unable to set read format to linear!\n");
|
||||
}
|
||||
if (!(dsp = ast_dsp_new())) {
|
||||
ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
|
||||
res = -1;
|
||||
}
|
||||
if (!res) {
|
||||
ast_stopstream(chan);
|
||||
res = ast_streamfile(chan, tmp, chan->language);
|
||||
if (!res) {
|
||||
while(chan->stream) {
|
||||
res = ast_sched_wait(chan->sched);
|
||||
if ((res < 0) && !chan->timingfunc) {
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
if (res < 0)
|
||||
res = 1000;
|
||||
res = ast_waitfor(chan, res);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Waitfor failed on %s\n", chan->name);
|
||||
break;
|
||||
} else if (res > 0) {
|
||||
fr = ast_read(chan);
|
||||
if (!fr) {
|
||||
res = -1;
|
||||
break;
|
||||
} else if (fr->frametype == AST_FRAME_DTMF) {
|
||||
char t[2];
|
||||
t[0] = fr->subclass;
|
||||
t[1] = '\0';
|
||||
if (ast_canmatch_extension(chan, chan->context, t, 1, chan->callerid)) {
|
||||
/* They entered a valid extension, or might be anyhow */
|
||||
res = fr->subclass;
|
||||
ast_frfree(fr);
|
||||
break;
|
||||
}
|
||||
} else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass == AST_FORMAT_SLINEAR)) {
|
||||
int totalsilence;
|
||||
int ms;
|
||||
res = ast_dsp_silence(dsp, fr, &totalsilence);
|
||||
if (res && (totalsilence > sil)) {
|
||||
/* We've been quiet a little while */
|
||||
if (notsilent) {
|
||||
/* We had heard some talking */
|
||||
gettimeofday(&end, NULL);
|
||||
ms = (end.tv_sec - start.tv_sec) * 1000;
|
||||
ms += (end.tv_usec - start.tv_usec) / 1000;
|
||||
ms -= sil;
|
||||
if (ms < 0)
|
||||
ms = 0;
|
||||
if ((ms > min) && ((max < 0) || (ms < max))) {
|
||||
ast_log(LOG_DEBUG, "Found qualified token of %d ms\n", ms);
|
||||
if (ast_exists_extension(chan, chan->context, "talk", 1, chan->callerid)) {
|
||||
strncpy(chan->exten, "talk", sizeof(chan->exten) -1 );
|
||||
chan->priority = 0;
|
||||
}
|
||||
res = 0;
|
||||
ast_frfree(fr);
|
||||
break;
|
||||
} else
|
||||
ast_log(LOG_DEBUG, "Found unqualified token of %d ms\n", ms);
|
||||
notsilent = 0;
|
||||
}
|
||||
} else {
|
||||
if (!notsilent) {
|
||||
/* Heard some audio, mark the begining of the token */
|
||||
gettimeofday(&start, NULL);
|
||||
ast_log(LOG_DEBUG, "Start of voice token!\n");
|
||||
notsilent = 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
ast_frfree(fr);
|
||||
}
|
||||
ast_sched_runq(chan->sched);
|
||||
}
|
||||
ast_stopstream(chan);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
if (res > -1) {
|
||||
if (origrformat && ast_set_read_format(chan, origrformat)) {
|
||||
ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n",
|
||||
chan->name, ast_getformatname(origrformat));
|
||||
}
|
||||
}
|
||||
if (dsp)
|
||||
ast_dsp_free(dsp);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, background_detect_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
473
apps/app_test.c
473
apps/app_test.c
@@ -1,473 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Applications to test connection and produce report in text file
|
||||
*
|
||||
* Copyright (C) 2004, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
* Russell Bryant <russelb@clemson.edu>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include "../astconf.h"
|
||||
|
||||
|
||||
static char *tdesc = "Interface Test Application";
|
||||
|
||||
static char *tests_descrip =
|
||||
"TestServer(): Perform test server function and write call report.\n"
|
||||
"Results stored in /var/log/asterisk/testreports/<testid>-server.txt";
|
||||
static char *tests_app = "TestServer";
|
||||
static char *tests_synopsis = "Execute Interface Test Server";
|
||||
|
||||
static char *testc_descrip =
|
||||
"TestClient(testid): Executes test client with given testid.\n"
|
||||
"Results stored in /var/log/asterisk/testreports/<testid>-client.txt";
|
||||
|
||||
static char *testc_app = "TestClient";
|
||||
static char *testc_synopsis = "Execute Interface Test Client";
|
||||
|
||||
static int measurenoise(struct ast_channel *chan, int ms, char *who)
|
||||
{
|
||||
int res=0;
|
||||
int mssofar;
|
||||
int noise=0;
|
||||
int samples=0;
|
||||
int x;
|
||||
short *foo;
|
||||
struct timeval start, tv;
|
||||
struct ast_frame *f;
|
||||
int rformat;
|
||||
rformat = chan->readformat;
|
||||
if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
|
||||
ast_log(LOG_NOTICE, "Unable to set to linear mode!\n");
|
||||
return -1;
|
||||
}
|
||||
gettimeofday(&start, NULL);
|
||||
for(;;) {
|
||||
gettimeofday(&tv, NULL);
|
||||
mssofar = (tv.tv_sec - start.tv_sec) * 1000;
|
||||
mssofar += (tv.tv_usec - start.tv_usec) / 1000;
|
||||
if (mssofar > ms)
|
||||
break;
|
||||
res = ast_waitfor(chan, ms - mssofar);
|
||||
if (res < 1)
|
||||
break;
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) {
|
||||
foo = (short *)f->data;
|
||||
for (x=0;x<f->samples;x++) {
|
||||
noise += abs(foo[x]);
|
||||
samples++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rformat) {
|
||||
if (ast_set_read_format(chan, rformat)) {
|
||||
ast_log(LOG_NOTICE, "Unable to restore original format!\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (res < 0)
|
||||
return res;
|
||||
if (!samples) {
|
||||
ast_log(LOG_NOTICE, "No samples were received from the other side!\n");
|
||||
return -1;
|
||||
}
|
||||
ast_log(LOG_DEBUG, "%s: Noise: %d, samples: %d, avg: %d\n", who, noise, samples, noise / samples);
|
||||
return (noise / samples);
|
||||
}
|
||||
|
||||
static int sendnoise(struct ast_channel *chan, int ms)
|
||||
{
|
||||
int res;
|
||||
res = ast_tonepair_start(chan, 1537, 2195, ms, 8192);
|
||||
if (!res) {
|
||||
res = ast_waitfordigit(chan, ms);
|
||||
ast_tonepair_stop(chan);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int testclient_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct localuser *u;
|
||||
int res = 0;
|
||||
char *testid=data;
|
||||
char fn[80];
|
||||
char serverver[80];
|
||||
FILE *f;
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Check for test id */
|
||||
if (!testid || ast_strlen_zero(testid)) {
|
||||
ast_log(LOG_WARNING, "TestClient requires an argument - the test id\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
res = ast_answer(chan);
|
||||
|
||||
/* Wait a few just to be sure things get started */
|
||||
res = ast_safe_sleep(chan, 3000);
|
||||
/* Transmit client version */
|
||||
if (!res)
|
||||
res = ast_dtmf_stream(chan, NULL, "8378*1#", 0);
|
||||
ast_log(LOG_DEBUG, "Transmit client version\n");
|
||||
|
||||
/* Read server version */
|
||||
ast_log(LOG_DEBUG, "Read server version\n");
|
||||
if (!res)
|
||||
res = ast_app_getdata(chan, NULL, serverver, sizeof(serverver) - 1, 0);
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
ast_log(LOG_DEBUG, "server version: %s\n", serverver);
|
||||
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
|
||||
if (!res)
|
||||
res = ast_safe_sleep(chan, 1000);
|
||||
/* Send test id */
|
||||
if (!res)
|
||||
res = ast_dtmf_stream(chan, NULL, testid, 0);
|
||||
if (!res)
|
||||
res = ast_dtmf_stream(chan, NULL, "#", 0);
|
||||
ast_log(LOG_DEBUG, "send test identifier: %s\n", testid);
|
||||
|
||||
if ((res >=0) && (!ast_strlen_zero(testid))) {
|
||||
/* Make the directory to hold the test results in case it's not there */
|
||||
snprintf(fn, sizeof(fn), "%s/testresults", ast_config_AST_LOG_DIR);
|
||||
mkdir(fn, 0777);
|
||||
snprintf(fn, sizeof(fn), "%s/testresults/%s-client.txt", ast_config_AST_LOG_DIR, testid);
|
||||
if ((f = fopen(fn, "w+"))) {
|
||||
setlinebuf(f);
|
||||
fprintf(f, "CLIENTCHAN: %s\n", chan->name);
|
||||
fprintf(f, "CLIENTTEST ID: %s\n", testid);
|
||||
fprintf(f, "ANSWER: PASS\n");
|
||||
res = 0;
|
||||
|
||||
if (!res) {
|
||||
/* Step 1: Wait for "1" */
|
||||
ast_log(LOG_DEBUG, "TestClient: 2. Wait DTMF 1\n");
|
||||
res = ast_waitfordigit(chan, 3000);
|
||||
fprintf(f, "WAIT DTMF 1: %s\n", (res != '1') ? "FAIL" : "PASS");
|
||||
if (res == '1')
|
||||
res = 0;
|
||||
else
|
||||
res = -1;
|
||||
}
|
||||
if (!res)
|
||||
res = ast_safe_sleep(chan, 1000);
|
||||
if (!res) {
|
||||
/* Step 2: Send "2" */
|
||||
ast_log(LOG_DEBUG, "TestClient: 2. Send DTMF 2\n");
|
||||
res = ast_dtmf_stream(chan, NULL, "2", 0);
|
||||
fprintf(f, "SEND DTMF 2: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 3: Wait one second */
|
||||
ast_log(LOG_DEBUG, "TestClient: 3. Wait one second\n");
|
||||
res = ast_safe_sleep(chan, 1000);
|
||||
fprintf(f, "WAIT 1 SEC: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 4: Measure noise */
|
||||
ast_log(LOG_DEBUG, "TestClient: 4. Measure noise\n");
|
||||
res = measurenoise(chan, 5000, "TestClient");
|
||||
fprintf(f, "MEASURENOISE: %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 5: Wait for "4" */
|
||||
ast_log(LOG_DEBUG, "TestClient: 5. Wait DTMF 4\n");
|
||||
res = ast_waitfordigit(chan, 3000);
|
||||
fprintf(f, "WAIT DTMF 4: %s\n", (res != '4') ? "FAIL" : "PASS");
|
||||
if (res == '4')
|
||||
res = 0;
|
||||
else
|
||||
res = -1;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 6: Transmit tone noise */
|
||||
ast_log(LOG_DEBUG, "TestClient: 6. Transmit tone\n");
|
||||
res = sendnoise(chan, 6000);
|
||||
fprintf(f, "SENDTONE: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
}
|
||||
if (!res || (res == '5')) {
|
||||
/* Step 7: Wait for "5" */
|
||||
ast_log(LOG_DEBUG, "TestClient: 7. Wait DTMF 5\n");
|
||||
if (!res)
|
||||
res = ast_waitfordigit(chan, 3000);
|
||||
fprintf(f, "WAIT DTMF 5: %s\n", (res != '5') ? "FAIL" : "PASS");
|
||||
if (res == '5')
|
||||
res = 0;
|
||||
else
|
||||
res = -1;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 8: Wait one second */
|
||||
ast_log(LOG_DEBUG, "TestClient: 8. Wait one second\n");
|
||||
res = ast_safe_sleep(chan, 1000);
|
||||
fprintf(f, "WAIT 1 SEC: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 9: Measure noise */
|
||||
ast_log(LOG_DEBUG, "TestClient: 6. Measure tone\n");
|
||||
res = measurenoise(chan, 4000, "TestClient");
|
||||
fprintf(f, "MEASURETONE: %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 10: Send "7" */
|
||||
ast_log(LOG_DEBUG, "TestClient: 7. Send DTMF 7\n");
|
||||
res = ast_dtmf_stream(chan, NULL, "7", 0);
|
||||
fprintf(f, "SEND DTMF 7: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
if (res > 0)
|
||||
res =0;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 11: Wait for "8" */
|
||||
ast_log(LOG_DEBUG, "TestClient: 11. Wait DTMF 8\n");
|
||||
res = ast_waitfordigit(chan, 3000);
|
||||
fprintf(f, "WAIT DTMF 8: %s\n", (res != '8') ? "FAIL" : "PASS");
|
||||
if (res == '8')
|
||||
res = 0;
|
||||
else
|
||||
res = -1;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 12: Hangup! */
|
||||
ast_log(LOG_DEBUG, "TestClient: 12. Hangup\n");
|
||||
}
|
||||
|
||||
ast_log(LOG_DEBUG, "-- TEST COMPLETE--\n");
|
||||
fprintf(f, "-- END TEST--\n");
|
||||
fclose(f);
|
||||
res = -1;
|
||||
} else
|
||||
res = -1;
|
||||
} else {
|
||||
ast_log(LOG_NOTICE, "Did not read a test ID on '%s'\n", chan->name);
|
||||
res = -1;
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int testserver_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct localuser *u;
|
||||
int res = 0;
|
||||
char testid[80]="";
|
||||
char fn[80];
|
||||
FILE *f;
|
||||
LOCAL_USER_ADD(u);
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
res = ast_answer(chan);
|
||||
/* Read version */
|
||||
ast_log(LOG_DEBUG, "Read client version\n");
|
||||
if (!res)
|
||||
res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
ast_log(LOG_DEBUG, "client version: %s\n", testid);
|
||||
ast_log(LOG_DEBUG, "Transmit server version\n");
|
||||
res = ast_safe_sleep(chan, 1000);
|
||||
if (!res)
|
||||
res = ast_dtmf_stream(chan, NULL, "8378*1#", 0);
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
|
||||
if (!res)
|
||||
res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);
|
||||
ast_log(LOG_DEBUG, "read test identifier: %s\n", testid);
|
||||
/* Check for sneakyness */
|
||||
if (strchr(testid, '/'))
|
||||
res = -1;
|
||||
if ((res >=0) && (!ast_strlen_zero(testid))) {
|
||||
/* Got a Test ID! Whoo hoo! */
|
||||
/* Make the directory to hold the test results in case it's not there */
|
||||
snprintf(fn, sizeof(fn), "%s/testresults", ast_config_AST_LOG_DIR);
|
||||
mkdir(fn, 0777);
|
||||
snprintf(fn, sizeof(fn), "%s/testresults/%s-server.txt", ast_config_AST_LOG_DIR, testid);
|
||||
if ((f = fopen(fn, "w+"))) {
|
||||
setlinebuf(f);
|
||||
fprintf(f, "SERVERCHAN: %s\n", chan->name);
|
||||
fprintf(f, "SERVERTEST ID: %s\n", testid);
|
||||
fprintf(f, "ANSWER: PASS\n");
|
||||
ast_log(LOG_DEBUG, "Processing Test ID '%s'\n", testid);
|
||||
res = ast_safe_sleep(chan, 1000);
|
||||
if (!res) {
|
||||
/* Step 1: Send "1" */
|
||||
ast_log(LOG_DEBUG, "TestServer: 1. Send DTMF 1\n");
|
||||
res = ast_dtmf_stream(chan, NULL, "1", 0);
|
||||
fprintf(f, "SEND DTMF 1: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 2: Wait for "2" */
|
||||
ast_log(LOG_DEBUG, "TestServer: 2. Wait DTMF 2\n");
|
||||
res = ast_waitfordigit(chan, 3000);
|
||||
fprintf(f, "WAIT DTMF 2: %s\n", (res != '2') ? "FAIL" : "PASS");
|
||||
if (res == '2')
|
||||
res = 0;
|
||||
else
|
||||
res = -1;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 3: Measure noise */
|
||||
ast_log(LOG_DEBUG, "TestServer: 3. Measure noise\n");
|
||||
res = measurenoise(chan, 6000, "TestServer");
|
||||
fprintf(f, "MEASURENOISE: %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 4: Send "4" */
|
||||
ast_log(LOG_DEBUG, "TestServer: 4. Send DTMF 4\n");
|
||||
res = ast_dtmf_stream(chan, NULL, "4", 0);
|
||||
fprintf(f, "SEND DTMF 4: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
/* Step 5: Wait one second */
|
||||
ast_log(LOG_DEBUG, "TestServer: 5. Wait one second\n");
|
||||
res = ast_safe_sleep(chan, 1000);
|
||||
fprintf(f, "WAIT 1 SEC: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
/* Step 6: Measure noise */
|
||||
ast_log(LOG_DEBUG, "TestServer: 6. Measure tone\n");
|
||||
res = measurenoise(chan, 4000, "TestServer");
|
||||
fprintf(f, "MEASURETONE: %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
/* Step 7: Send "5" */
|
||||
ast_log(LOG_DEBUG, "TestServer: 7. Send DTMF 5\n");
|
||||
res = ast_dtmf_stream(chan, NULL, "5", 0);
|
||||
fprintf(f, "SEND DTMF 5: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
/* Step 8: Transmit tone noise */
|
||||
ast_log(LOG_DEBUG, "TestServer: 8. Transmit tone\n");
|
||||
res = sendnoise(chan, 6000);
|
||||
fprintf(f, "SENDTONE: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
}
|
||||
|
||||
if (!res || (res == '7')) {
|
||||
/* Step 9: Wait for "7" */
|
||||
ast_log(LOG_DEBUG, "TestServer: 9. Wait DTMF 7\n");
|
||||
if (!res)
|
||||
res = ast_waitfordigit(chan, 3000);
|
||||
fprintf(f, "WAIT DTMF 7: %s\n", (res != '7') ? "FAIL" : "PASS");
|
||||
if (res == '7')
|
||||
res = 0;
|
||||
else
|
||||
res = -1;
|
||||
}
|
||||
if (!res)
|
||||
res = ast_safe_sleep(chan, 1000);
|
||||
if (!res) {
|
||||
/* Step 10: Send "8" */
|
||||
ast_log(LOG_DEBUG, "TestServer: 10. Send DTMF 8\n");
|
||||
res = ast_dtmf_stream(chan, NULL, "8", 0);
|
||||
fprintf(f, "SEND DTMF 8: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 11: Wait for hangup to arrive! */
|
||||
ast_log(LOG_DEBUG, "TestServer: 11. Waiting for hangup\n");
|
||||
res = ast_safe_sleep(chan, 10000);
|
||||
fprintf(f, "WAIT HANGUP: %s\n", (res < 0) ? "PASS" : "FAIL");
|
||||
}
|
||||
|
||||
ast_log(LOG_DEBUG, "-- TEST COMPLETE--\n");
|
||||
fprintf(f, "-- END TEST--\n");
|
||||
fclose(f);
|
||||
res = -1;
|
||||
} else
|
||||
res = -1;
|
||||
} else {
|
||||
ast_log(LOG_NOTICE, "Did not read a test ID on '%s'\n", chan->name);
|
||||
res = -1;
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
ast_unregister_application(testc_app);
|
||||
return ast_unregister_application(tests_app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
ast_register_application(testc_app, testclient_exec, testc_synopsis, testc_descrip);
|
||||
return ast_register_application(tests_app, testserver_exec, tests_synopsis, tests_descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key(void)
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Transfer a caller
|
||||
* Time of day - Report the time of day
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
@@ -22,6 +22,9 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "Transfer";
|
||||
|
||||
static char *app = "Transfer";
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Caller*id name lookup - Look up the caller's name via DNS
|
||||
*
|
||||
* Copyright (C) 1999-2004, Digium
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/config.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/enum.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static char *tdesc = "TXTCIDName";
|
||||
|
||||
static char *app = "TXTCIDName";
|
||||
|
||||
static char *synopsis = "Lookup caller name from TXT record";
|
||||
|
||||
static char *descrip =
|
||||
" TXTLookup(CallerID): Looks up a Caller Name via DNS and sets\n"
|
||||
"the variable 'TXTCIDNAME'. TXTCIDName will either be blank\n"
|
||||
"or return the value found in the TXT record in DNS.\n" ;
|
||||
|
||||
#define ENUM_CONFIG "enum.conf"
|
||||
|
||||
static char h323driver[80] = "";
|
||||
#define H323DRIVERDEFAULT "H323"
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int txtcidname_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
char tech[80];
|
||||
char txt[256] = "";
|
||||
char dest[80];
|
||||
|
||||
struct localuser *u;
|
||||
if (!data || !strlen(data)) {
|
||||
ast_log(LOG_WARNING, "TXTCIDName requires an argument (extension)\n");
|
||||
res = 1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
if (!res) {
|
||||
res = ast_get_txt(chan, data, dest, sizeof(dest), tech, sizeof(tech), txt, sizeof(txt));
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
/* Parse it out */
|
||||
if (res > 0) {
|
||||
if (!ast_strlen_zero(txt)) {
|
||||
pbx_builtin_setvar_helper(chan, "TXTCIDNAME", txt);
|
||||
#if 0
|
||||
ast_log(LOG_DEBUG, "TXTCIDNAME got '%s'\n", txt);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (!res) {
|
||||
/* Look for a "busy" place */
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
} else if (res > 0)
|
||||
res = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_config(void)
|
||||
{
|
||||
struct ast_config *cfg;
|
||||
char *s;
|
||||
|
||||
cfg = ast_load(ENUM_CONFIG);
|
||||
if (cfg) {
|
||||
if (!(s=ast_variable_retrieve(cfg, "general", "h323driver"))) {
|
||||
strncpy(h323driver, H323DRIVERDEFAULT, sizeof(h323driver) - 1);
|
||||
} else {
|
||||
strncpy(h323driver, s, sizeof(h323driver) - 1);
|
||||
}
|
||||
ast_destroy(cfg);
|
||||
return 0;
|
||||
}
|
||||
ast_log(LOG_NOTICE, "No ENUM Config file, using defaults\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
res = ast_register_application(app, txtcidname_exec, synopsis, descrip);
|
||||
if (res)
|
||||
return(res);
|
||||
if ((res=load_config())) {
|
||||
return(res);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int reload(void)
|
||||
{
|
||||
return(load_config());
|
||||
}
|
||||
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <asterisk/image.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Send URL Applications";
|
||||
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* UserEvent application -- send manager event
|
||||
*
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/manager.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static char *tdesc = "Custom User Event Application";
|
||||
|
||||
static char *app = "UserEvent";
|
||||
|
||||
static char *synopsis = "Send an arbitrary event to the manager interface";
|
||||
|
||||
static char *descrip =
|
||||
" UserEvent(eventname[|body]): Sends an arbitrary event to the\n"
|
||||
"manager interface, with an optional body representing additional\n"
|
||||
"arguments. The format of the event will be:\n"
|
||||
" Event: UserEvent<specified event name>\n"
|
||||
" Channel: <channel name>\n"
|
||||
" Uniqueid: <call uniqueid>\n"
|
||||
" [body]\n"
|
||||
"If the body is not specified, only Event, Channel, and Uniqueid fields\n"
|
||||
"will be present. Returns 0.";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int userevent_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct localuser *u;
|
||||
char info[512];
|
||||
char eventname[512];
|
||||
char *eventbody;
|
||||
|
||||
if (!data || !strlen(data)) {
|
||||
ast_log(LOG_WARNING, "UserEvent requires an argument (eventname|optional event body)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1);
|
||||
snprintf(eventname, sizeof(eventname), "UserEvent%s", info);
|
||||
eventbody = strchr(eventname, '|');
|
||||
if (eventbody) {
|
||||
*eventbody = '\0';
|
||||
eventbody++;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if(eventbody) {
|
||||
ast_log(LOG_DEBUG, "Sending user event: %s, %s\n", eventname, eventbody);
|
||||
manager_event(EVENT_FLAG_CALL, eventname,
|
||||
"Channel: %s\r\nUniqueid: %s\r\n%s\r\n",
|
||||
chan->name, chan->uniqueid, eventbody);
|
||||
} else {
|
||||
ast_log(LOG_DEBUG, "Sending user event: %s\n", eventname);
|
||||
manager_event(EVENT_FLAG_CALL, eventname,
|
||||
"Channel: %s\r\nUniqueid: %s\r\n", chan->name, chan->uniqueid);
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, userevent_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Verbose application
|
||||
*
|
||||
* Copyright (c) 2004 Tilghman Lesher. All rights reserved.
|
||||
*
|
||||
* Tilghman Lesher <app_verbose_v001@the-tilghman.com>
|
||||
*
|
||||
* This code is released by the author with no restrictions on usage.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
|
||||
|
||||
static char *tdesc = "Send verbose output";
|
||||
|
||||
static char *app_verbose = "Verbose";
|
||||
|
||||
static char *verbose_synopsis = "Send arbitrary text to verbose output";
|
||||
|
||||
static char *verbose_descrip =
|
||||
"Verbose([<level>|]<message>)\n"
|
||||
" level must be an integer value. If not specified, defaults to 0."
|
||||
" Always returns 0.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int verbose_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
char *vtext;
|
||||
int vsize;
|
||||
|
||||
if (data) {
|
||||
vtext = ast_strdupa((char *)data);
|
||||
if (vtext) {
|
||||
char *tmp = strsep(&vtext, "|,");
|
||||
if (vtext) {
|
||||
if (sscanf(tmp, "%d", &vsize) != 1) {
|
||||
vsize = 0;
|
||||
ast_log(LOG_WARNING, "'%s' is not a verboser number\n", vtext);
|
||||
}
|
||||
} else {
|
||||
vtext = tmp;
|
||||
vsize = 0;
|
||||
}
|
||||
if (option_verbose >= vsize) {
|
||||
switch (vsize) {
|
||||
case 0:
|
||||
ast_verbose("%s\n", vtext);
|
||||
break;
|
||||
case 1:
|
||||
ast_verbose(VERBOSE_PREFIX_1 "%s\n", vtext);
|
||||
break;
|
||||
case 2:
|
||||
ast_verbose(VERBOSE_PREFIX_2 "%s\n", vtext);
|
||||
break;
|
||||
case 3:
|
||||
ast_verbose(VERBOSE_PREFIX_3 "%s\n", vtext);
|
||||
break;
|
||||
default:
|
||||
ast_verbose(VERBOSE_PREFIX_4 "%s\n", vtext);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app_verbose);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app_verbose, verbose_exec, verbose_synopsis, verbose_descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
3555
apps/app_voicemail.c
3555
apps/app_voicemail.c
File diff suppressed because it is too large
Load Diff
@@ -18,12 +18,14 @@
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *synopsis = "Wait for Ring Application";
|
||||
|
||||
static char *tdesc = "Waits until first ring after time";
|
||||
@@ -46,7 +48,7 @@ static int waitforring_exec(struct ast_channel *chan, void *data)
|
||||
int res = 0;
|
||||
int ms;
|
||||
if (!data || (sscanf(data, "%d", &ms) != 1)) {
|
||||
ast_log(LOG_WARNING, "WaitForRing requires an argument (minimum seconds)\n");
|
||||
ast_log(LOG_WARNING, "SoftHangup requires an argument (minimum seconds)\n");
|
||||
return 0;
|
||||
}
|
||||
ms *= 1000;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <asterisk/translate.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Block Telemarketers with Special Information Tone";
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/cli.h>
|
||||
#include <asterisk/say.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
@@ -33,12 +32,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifdef __linux__
|
||||
#include <pthread.h>
|
||||
#include <linux/zaptel.h>
|
||||
#else
|
||||
#include <zaptel.h>
|
||||
#endif /* __linux__ */
|
||||
|
||||
static char *tdesc = "Barge in on Zap channel application";
|
||||
|
||||
static char *app = "ZapBarge";
|
||||
@@ -249,9 +244,9 @@ static int conf_exec(struct ast_channel *chan, void *data)
|
||||
int retrycnt = 0;
|
||||
int confflags = 0;
|
||||
int confno = 0;
|
||||
char confstr[80] = "";
|
||||
char confstr[80];
|
||||
|
||||
if (data && !ast_strlen_zero(data)) {
|
||||
if (data && strlen(data)) {
|
||||
if ((sscanf(data, "Zap/%d", &confno) != 1) &&
|
||||
(sscanf(data, "%d", &confno) != 1)) {
|
||||
ast_log(LOG_WARNING, "ZapBarge Argument (if specified) must be a channel number, not '%s'\n", (char *)data);
|
||||
@@ -264,7 +259,7 @@ static int conf_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
while(!confno && (++retrycnt < 4)) {
|
||||
/* Prompt user for conference number */
|
||||
confstr[0] = '\0';
|
||||
strcpy(confstr, "");
|
||||
res = ast_app_getdata(chan, "conf-getchannel",confstr, sizeof(confstr) - 1, 0);
|
||||
if (res <0) goto out;
|
||||
if (sscanf(confstr, "%d", &confno) != 1)
|
||||
|
||||
@@ -20,11 +20,7 @@
|
||||
#include <asterisk/options.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/wait.h>
|
||||
#ifdef __linux__
|
||||
#include <sys/signal.h>
|
||||
#else
|
||||
#include <signal.h>
|
||||
#endif /* __linux__ */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@@ -34,12 +30,10 @@
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
/* Need some zaptel help here */
|
||||
#ifdef __linux__
|
||||
#include <linux/zaptel.h>
|
||||
#else
|
||||
#include <zaptel.h>
|
||||
#endif /* __linux__ */
|
||||
|
||||
static char *tdesc = "Zap RAS Application";
|
||||
|
||||
@@ -50,7 +44,7 @@ static char *synopsis = "Executes Zaptel ISDN RAS application";
|
||||
static char *descrip =
|
||||
" ZapRAS(args): Executes a RAS server using pppd on the given channel.\n"
|
||||
"The channel must be a clear channel (i.e. PRI source) and a Zaptel\n"
|
||||
"channel to be able to use this function (No modem emulation is included).\n"
|
||||
"channel to be able to use this function (No modem emulcation is included).\n"
|
||||
"Your pppd must be patched to be zaptel aware. Arguments should be\n"
|
||||
"separated by | characters. Always returns -1.\n";
|
||||
|
||||
|
||||
@@ -34,12 +34,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifdef __linux__
|
||||
#include <pthread.h>
|
||||
#include <linux/zaptel.h>
|
||||
#else
|
||||
#include <zaptel.h>
|
||||
#endif /* __linux__ */
|
||||
|
||||
static char *tdesc = "Scan Zap channels application";
|
||||
|
||||
static char *app = "ZapScan";
|
||||
@@ -47,8 +43,8 @@ static char *app = "ZapScan";
|
||||
static char *synopsis = "Scan Zap channels to monitor calls";
|
||||
|
||||
static char *descrip =
|
||||
" ZapScan allows a call center manager to monitor Zap channels in\n"
|
||||
"a convenient way. Use '#' to select the next channel and use '*' to exit\n";
|
||||
" ZapScan allows a call center manager to monitor\n"
|
||||
"phone conversations in a convenient way.";
|
||||
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
@@ -58,22 +54,6 @@ LOCAL_USER_DECL;
|
||||
|
||||
#define CONF_SIZE 160
|
||||
|
||||
static struct ast_channel *get_zap_channel_locked(int num) {
|
||||
struct ast_channel *c=NULL;
|
||||
char name[80];
|
||||
|
||||
snprintf(name,sizeof(name),"Zap/%d-1",num);
|
||||
c = ast_channel_walk_locked(NULL);
|
||||
while(c) {
|
||||
if (!strcasecmp(c->name, name)) {
|
||||
break;
|
||||
}
|
||||
ast_mutex_unlock(&c->lock);
|
||||
c = ast_channel_walk_locked(c);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
static int careful_write(int fd, unsigned char *data, int len)
|
||||
{
|
||||
int res;
|
||||
@@ -107,8 +87,6 @@ static int conf_run(struct ast_channel *chan, int confno, int confflags)
|
||||
int retryzap;
|
||||
int origfd;
|
||||
int ret = -1;
|
||||
char input[4];
|
||||
int ic=0;
|
||||
|
||||
ZT_BUFFERINFO bi;
|
||||
char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
|
||||
@@ -210,30 +188,11 @@ zapretry:
|
||||
f = ast_read(c);
|
||||
if (!f)
|
||||
break;
|
||||
if(f->frametype == AST_FRAME_DTMF) {
|
||||
if(f->subclass == '#') {
|
||||
ret = 0;
|
||||
if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
else if (f->subclass == '*') {
|
||||
ret = -1;
|
||||
break;
|
||||
|
||||
}
|
||||
else {
|
||||
input[ic++] = f->subclass;
|
||||
}
|
||||
if(ic == 3) {
|
||||
input[ic++] = '\0';
|
||||
ic=0;
|
||||
ret = atoi(input);
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Zapscan: change channel to %d\n",ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fd != chan->fds[0]) {
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
} else if (fd != chan->fds[0]) {
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
if (f->subclass == AST_FORMAT_ULAW) {
|
||||
/* Carefully write */
|
||||
careful_write(fd, f->data, f->datalen);
|
||||
@@ -284,56 +243,33 @@ static int conf_exec(struct ast_channel *chan, void *data)
|
||||
struct localuser *u;
|
||||
int confflags = 0;
|
||||
int confno = 0;
|
||||
char confstr[80] = "", *tmp;
|
||||
struct ast_channel *tempchan = NULL, *lastchan = NULL,*ichan = NULL;
|
||||
struct ast_frame *f;
|
||||
int input=0;
|
||||
|
||||
char confstr[80], *tmp;
|
||||
struct ast_channel *tempchan = NULL, *lastchan = NULL;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
ast_answer(chan);
|
||||
|
||||
for (;;) {
|
||||
if (ast_waitfor(chan, 100) < 0)
|
||||
break;
|
||||
|
||||
f = ast_read(chan);
|
||||
if (!f)
|
||||
break;
|
||||
if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) {
|
||||
ast_frfree(f);
|
||||
break;
|
||||
tempchan = ast_channel_walk(tempchan);
|
||||
if ( !tempchan && !lastchan )
|
||||
break;
|
||||
if ( tempchan && (!strcmp(tempchan->type, "Zap")) && (tempchan != chan) ) {
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Zap channel %s is in-use, monitoring...\n", tempchan->name);
|
||||
strcpy(confstr, tempchan->name);
|
||||
if ((tmp = strchr(confstr,'-'))) {
|
||||
*tmp = '\0';
|
||||
}
|
||||
ast_frfree(f);
|
||||
ichan = NULL;
|
||||
if(input) {
|
||||
ichan = get_zap_channel_locked(input);
|
||||
input = 0;
|
||||
}
|
||||
|
||||
tempchan = ichan ? ichan : ast_channel_walk_locked(tempchan);
|
||||
|
||||
|
||||
if ( !tempchan && !lastchan )
|
||||
break;
|
||||
if ( tempchan && tempchan->type && (!strcmp(tempchan->type, "Zap")) && (tempchan != chan) ) {
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Zap channel %s is in-use, monitoring...\n", tempchan->name);
|
||||
strncpy(confstr, tempchan->name, sizeof(confstr) - 1);
|
||||
ast_mutex_unlock(&tempchan->lock);
|
||||
if ((tmp = strchr(confstr,'-'))) {
|
||||
*tmp = '\0';
|
||||
}
|
||||
confno = atoi(strchr(confstr,'/') + 1);
|
||||
ast_stopstream(chan);
|
||||
ast_say_number(chan, confno, AST_DIGIT_ANY, chan->language, (char *) NULL);
|
||||
res = conf_run(chan, confno, confflags);
|
||||
if (res<0) break;
|
||||
input = res;
|
||||
} else if (tempchan)
|
||||
ast_mutex_unlock(&tempchan->lock);
|
||||
lastchan = tempchan;
|
||||
confno = atoi(strchr(confstr,'/') + 1);
|
||||
ast_stopstream(chan);
|
||||
ast_say_number(chan, confno, AST_DIGIT_ANY, chan->language);
|
||||
res = conf_run(chan, confno, confflags);
|
||||
if (res<0) break;
|
||||
}
|
||||
lastchan = tempchan;
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
Binary file not shown.
257
ast_expr.y
257
ast_expr.y
@@ -20,13 +20,6 @@
|
||||
#include <asterisk/ast_expr.h>
|
||||
#include <asterisk/logger.h>
|
||||
|
||||
#ifdef LONG_LONG_MIN
|
||||
#define QUAD_MIN LONG_LONG_MIN
|
||||
#endif
|
||||
#ifdef LONG_LONG_MAX
|
||||
#define QUAD_MAX LONG_LONG_MAX
|
||||
#endif
|
||||
|
||||
# if ! defined(QUAD_MIN)
|
||||
# define QUAD_MIN (-0x7fffffffffffffffL-1)
|
||||
# endif
|
||||
@@ -55,7 +48,6 @@ struct val {
|
||||
struct parser_control {
|
||||
struct val *result;
|
||||
int pipa;
|
||||
char *arg_orig;
|
||||
char *argv;
|
||||
char *ptrptr;
|
||||
int firsttoken;
|
||||
@@ -86,30 +78,10 @@ static struct val *op_rem __P((struct val *, struct val *));
|
||||
static struct val *op_times __P((struct val *, struct val *));
|
||||
static quad_t to_integer __P((struct val *));
|
||||
static void to_string __P((struct val *));
|
||||
|
||||
/* uh, if I want to predeclare yylex with a YYLTYPE, I have to predeclare the yyltype... sigh */
|
||||
typedef struct yyltype
|
||||
{
|
||||
int first_line;
|
||||
int first_column;
|
||||
|
||||
int last_line;
|
||||
int last_column;
|
||||
} yyltype;
|
||||
|
||||
# define YYLTYPE yyltype
|
||||
# define YYLTYPE_IS_TRIVIAL 1
|
||||
|
||||
static int ast_yyerror __P((const char *,YYLTYPE *, struct parser_control *));
|
||||
|
||||
#define ast_yyerror(x) ast_yyerror(x,&yyloc,kota)
|
||||
|
||||
static int ast_yyerror __P((const char *));
|
||||
%}
|
||||
|
||||
%pure-parser
|
||||
%locations
|
||||
/* %debug for when you are having big problems */
|
||||
|
||||
/* %name-prefix="ast_yy" */
|
||||
|
||||
%union
|
||||
@@ -118,7 +90,7 @@ static int ast_yyerror __P((const char *,YYLTYPE *, struct parser_control *));
|
||||
}
|
||||
|
||||
%{
|
||||
static int ast_yylex __P((YYSTYPE *, YYLTYPE *, struct parser_control *));
|
||||
static int ast_yylex __P((YYSTYPE *, struct parser_control *));
|
||||
%}
|
||||
|
||||
|
||||
@@ -138,21 +110,21 @@ start: expr { ((struct parser_control *)kota)->result = $$; }
|
||||
;
|
||||
|
||||
expr: TOKEN
|
||||
| '(' expr ')' { $$ = $2; @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr '|' expr { $$ = op_or ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr '&' expr { $$ = op_and ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr '=' expr { $$ = op_eq ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr '>' expr { $$ = op_gt ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr '<' expr { $$ = op_lt ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr GE expr { $$ = op_ge ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr LE expr { $$ = op_le ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr NE expr { $$ = op_ne ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr '+' expr { $$ = op_plus ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr '-' expr { $$ = op_minus ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr '*' expr { $$ = op_times ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr '/' expr { $$ = op_div ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr '%' expr { $$ = op_rem ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr ':' expr { $$ = op_colon ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| '(' expr ')' { $$ = $2; }
|
||||
| expr '|' expr { $$ = op_or ($1, $3); }
|
||||
| expr '&' expr { $$ = op_and ($1, $3); }
|
||||
| expr '=' expr { $$ = op_eq ($1, $3); }
|
||||
| expr '>' expr { $$ = op_gt ($1, $3); }
|
||||
| expr '<' expr { $$ = op_lt ($1, $3); }
|
||||
| expr GE expr { $$ = op_ge ($1, $3); }
|
||||
| expr LE expr { $$ = op_le ($1, $3); }
|
||||
| expr NE expr { $$ = op_ne ($1, $3); }
|
||||
| expr '+' expr { $$ = op_plus ($1, $3); }
|
||||
| expr '-' expr { $$ = op_minus ($1, $3); }
|
||||
| expr '*' expr { $$ = op_times ($1, $3); }
|
||||
| expr '/' expr { $$ = op_div ($1, $3); }
|
||||
| expr '%' expr { $$ = op_rem ($1, $3); }
|
||||
| expr ':' expr { $$ = op_colon ($1, $3); }
|
||||
;
|
||||
|
||||
|
||||
@@ -215,7 +187,6 @@ struct val *vp;
|
||||
}
|
||||
if (vp->type == string || vp->type == numeric_string)
|
||||
free (vp->u.s);
|
||||
free (vp);
|
||||
}
|
||||
|
||||
|
||||
@@ -279,92 +250,19 @@ struct val *vp;
|
||||
return (vp->type == string);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ast_yylex (YYSTYPE *lvalp, YYLTYPE *yylloc, struct parser_control *karoto)
|
||||
ast_yylex (YYSTYPE *lvalp, struct parser_control *karoto)
|
||||
{
|
||||
char *p=0;
|
||||
char *t1=0;
|
||||
char savep = 0;
|
||||
char *savepp = 0;
|
||||
|
||||
char *p;
|
||||
|
||||
if (karoto->firsttoken==1) {
|
||||
t1 = karoto->argv;
|
||||
karoto->firsttoken = 0;
|
||||
p=strtok_r(karoto->argv," ",&(karoto->ptrptr));
|
||||
karoto->firsttoken=0;
|
||||
} else {
|
||||
t1 = karoto->ptrptr;
|
||||
p=strtok_r(NULL," ",&(karoto->ptrptr));
|
||||
}
|
||||
|
||||
while(*t1 && *t1 == ' ' ) /* we can remove worries about leading/multiple spaces being present */
|
||||
t1++;
|
||||
karoto->ptrptr = t1;
|
||||
yylloc->first_column = t1 - karoto->argv;
|
||||
|
||||
while( *t1 && *t1 != ' ' && *t1 != '"') /* find the next space or quote */
|
||||
t1++;
|
||||
if( *t1 == ' ' )
|
||||
{
|
||||
*t1 = 0;
|
||||
p = karoto->ptrptr;
|
||||
karoto->ptrptr = t1+1;
|
||||
yylloc->last_column = t1 - karoto->argv;
|
||||
}
|
||||
else if (*t1 == '"' )
|
||||
{
|
||||
/* opening quote. find the closing quote */
|
||||
char *t2=t1+1;
|
||||
while( *t2 && *t2 != '"')
|
||||
t2++;
|
||||
if( *t2 == '"' )
|
||||
{
|
||||
if( *(t2+1) == ' ' || *(t2+1) == 0 )
|
||||
{
|
||||
if( *(t2+1) )
|
||||
{
|
||||
*(t2+1) = 0;
|
||||
karoto->ptrptr = t2+2;
|
||||
}
|
||||
else
|
||||
{
|
||||
karoto->ptrptr = t2+1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* hmmm. what if another token is here? */
|
||||
/* maybe we can insert a space? */
|
||||
savep = *(t2+1);
|
||||
savepp = t2+1;
|
||||
*(t2+1) = 0;
|
||||
karoto->ptrptr = t2+1;
|
||||
}
|
||||
p = t1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* NOT GOOD -- no closing quote! */
|
||||
p = t1;
|
||||
karoto->ptrptr = t2;
|
||||
}
|
||||
yylloc->last_column = t2 - karoto->argv;
|
||||
}
|
||||
else if( *t1 == 0 )
|
||||
{
|
||||
if( t1 != karoto->ptrptr )
|
||||
{
|
||||
/* this is the last token */
|
||||
p = karoto->ptrptr;
|
||||
karoto->ptrptr = t1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we are done. That was quick */
|
||||
p = karoto->ptrptr;
|
||||
yylloc->last_column = t1 - karoto->argv;
|
||||
}
|
||||
}
|
||||
if( *p == 0 )
|
||||
p = 0;
|
||||
|
||||
|
||||
if (p==NULL) {
|
||||
return (0);
|
||||
}
|
||||
@@ -382,12 +280,6 @@ ast_yylex (YYSTYPE *lvalp, YYLTYPE *yylloc, struct parser_control *karoto)
|
||||
}
|
||||
|
||||
lvalp->val = make_str (p);
|
||||
if( savep )
|
||||
{
|
||||
*savepp = savep; /* restore the null terminated string */
|
||||
savepp = 0;
|
||||
savep = 0;
|
||||
}
|
||||
return (TOKEN);
|
||||
}
|
||||
|
||||
@@ -414,9 +306,7 @@ char *ast_expr (char *arg)
|
||||
karoto.result = NULL;
|
||||
karoto.firsttoken=1;
|
||||
karoto.argv=kota;
|
||||
karoto.arg_orig = arg;
|
||||
/* ast_yydebug = 1; */
|
||||
|
||||
|
||||
ast_yyparse ((void *)&karoto);
|
||||
|
||||
free(kota);
|
||||
@@ -449,31 +339,11 @@ int main(int argc,char **argv) {
|
||||
|
||||
#endif
|
||||
|
||||
#undef ast_yyerror
|
||||
#define ast_yyerror(x) ast_yyerror(x, YYLTYPE *yylloc, struct parser_control *karoto)
|
||||
|
||||
static int
|
||||
ast_yyerror (const char *s)
|
||||
ast_yyerror (s)
|
||||
const char *s;
|
||||
{
|
||||
char spacebuf[8000]; /* best safe than sorry */
|
||||
char spacebuf2[8000]; /* best safe than sorry */
|
||||
int i=0;
|
||||
spacebuf[0] = 0;
|
||||
|
||||
if( yylloc->first_column > 7990 ) /* if things get out of whack, why crash? */
|
||||
yylloc->first_column = 7990;
|
||||
if( yylloc->last_column > 7990 )
|
||||
yylloc->last_column = 7990;
|
||||
for(i=0;i<yylloc->first_column;i++) spacebuf[i] = ' ';
|
||||
for( ;i<yylloc->last_column;i++) spacebuf[i] = '^';
|
||||
spacebuf[i] = 0;
|
||||
|
||||
for(i=0;i<karoto->ptrptr-karoto->argv;i++) spacebuf2[i] = ' ';
|
||||
spacebuf2[i++]='^';
|
||||
spacebuf2[i]= 0;
|
||||
|
||||
ast_log(LOG_WARNING,"ast_yyerror(): syntax error: %s; Input:\n%s\n%s\n%s\n",s,
|
||||
karoto->arg_orig,spacebuf,spacebuf2);
|
||||
ast_log(LOG_WARNING,"ast_yyerror(): syntax error: %s\n",s);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -651,24 +521,19 @@ struct val *a, *b;
|
||||
{
|
||||
struct val *r;
|
||||
|
||||
if (!to_integer (a)) {
|
||||
if (!to_integer (a) || !to_integer (b)) {
|
||||
ast_log(LOG_WARNING,"non-numeric argument\n");
|
||||
if (!to_integer (b)) {
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return make_integer(0);
|
||||
} else {
|
||||
free_value(a);
|
||||
return (b);
|
||||
}
|
||||
} else if (!to_integer(b)) {
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return (a);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
r = make_integer (/*(quad_t)*/(a->u.i + b->u.i));
|
||||
if (chk_plus (a->u.i, b->u.i, r->u.i)) {
|
||||
ast_log(LOG_WARNING,"overflow\n");
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return(NULL);
|
||||
}
|
||||
free_value (a);
|
||||
free_value (b);
|
||||
@@ -696,27 +561,19 @@ struct val *a, *b;
|
||||
{
|
||||
struct val *r;
|
||||
|
||||
if (!to_integer (a)) {
|
||||
ast_log(LOG_WARNING, "non-numeric argument\n");
|
||||
if (!to_integer (b)) {
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return make_integer(0);
|
||||
} else {
|
||||
r = make_integer(0 - b->u.i);
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return (r);
|
||||
}
|
||||
} else if (!to_integer(b)) {
|
||||
ast_log(LOG_WARNING, "non-numeric argument\n");
|
||||
if (!to_integer (a) || !to_integer (b)) {
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return (a);
|
||||
ast_log(LOG_WARNING, "non-numeric argument\n");
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
r = make_integer (/*(quad_t)*/(a->u.i - b->u.i));
|
||||
if (chk_minus (a->u.i, b->u.i, r->u.i)) {
|
||||
ast_log(LOG_WARNING, "overflow\n");
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
ast_log(LOG_WARNING, "overload\n");
|
||||
return(NULL);
|
||||
}
|
||||
free_value (a);
|
||||
free_value (b);
|
||||
@@ -746,12 +603,15 @@ struct val *a, *b;
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
ast_log(LOG_WARNING, "non-numeric argument\n");
|
||||
return(make_integer(0));
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
r = make_integer (/*(quad_t)*/(a->u.i * b->u.i));
|
||||
if (chk_times (a->u.i, b->u.i, r->u.i)) {
|
||||
ast_log(LOG_WARNING, "overflow\n");
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return(NULL);
|
||||
}
|
||||
free_value (a);
|
||||
free_value (b);
|
||||
@@ -776,28 +636,26 @@ struct val *a, *b;
|
||||
{
|
||||
struct val *r;
|
||||
|
||||
if (!to_integer (a)) {
|
||||
if (!to_integer (a) || !to_integer (b)) {
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
ast_log(LOG_WARNING, "non-numeric argument\n");
|
||||
return make_integer(0);
|
||||
} else if (!to_integer (b)) {
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
ast_log(LOG_WARNING, "non-numeric argument\n");
|
||||
return make_integer(INT_MAX);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (b->u.i == 0) {
|
||||
ast_log(LOG_WARNING, "division by zero\n");
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return make_integer(INT_MAX);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
r = make_integer (/*(quad_t)*/(a->u.i / b->u.i));
|
||||
if (chk_div (a->u.i, b->u.i)) {
|
||||
ast_log(LOG_WARNING, "overflow\n");
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return(NULL);
|
||||
}
|
||||
free_value (a);
|
||||
free_value (b);
|
||||
@@ -814,13 +672,14 @@ struct val *a, *b;
|
||||
ast_log(LOG_WARNING, "non-numeric argument\n");
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return make_integer(0);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (b->u.i == 0) {
|
||||
ast_log(LOG_WARNING, "div by zero\n");
|
||||
free_value(a);
|
||||
return (b);
|
||||
free_value(b);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
r = make_integer (/*(quad_t)*/(a->u.i % b->u.i));
|
||||
@@ -845,12 +704,12 @@ struct val *a, *b;
|
||||
to_string(b);
|
||||
|
||||
/* compile regular expression */
|
||||
if ((eval = regcomp (&rp, b->u.s, REG_EXTENDED)) != 0) {
|
||||
if ((eval = regcomp (&rp, b->u.s, 0)) != 0) {
|
||||
regerror (eval, &rp, errbuf, sizeof(errbuf));
|
||||
ast_log(LOG_WARNING,"regcomp() error : %s",errbuf);
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return make_str("");
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* compare string against pattern */
|
||||
|
||||
BIN
asterisk.8.gz
BIN
asterisk.8.gz
Binary file not shown.
714
asterisk.c
714
asterisk.c
File diff suppressed because it is too large
Load Diff
@@ -28,7 +28,6 @@
|
||||
#define AST_AGI_DIR ASTAGIDIR
|
||||
#define AST_KEY_DIR ASTVARLIBDIR "/keys"
|
||||
#define AST_DB ASTVARLIBDIR "/astdb"
|
||||
#define AST_TMP_DIR ASTSPOOLDIR "/tmp"
|
||||
|
||||
#define AST_CONFIG_FILE ASTCONFPATH
|
||||
|
||||
@@ -41,7 +40,6 @@ extern int load_modules(void);
|
||||
extern int load_pbx(void);
|
||||
/* Provided by logger.c */
|
||||
extern int init_logger(void);
|
||||
extern void close_logger(void);
|
||||
/* Provided by frame.c */
|
||||
extern int init_framer(void);
|
||||
/* Provided by logger.c */
|
||||
|
||||
295
asterisk.sgml
295
asterisk.sgml
@@ -1,295 +0,0 @@
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
|
||||
<refentry>
|
||||
<refentryinfo>
|
||||
<date>2004-07-18</date>
|
||||
</refentryinfo>
|
||||
<refmeta>
|
||||
<refentrytitle>
|
||||
<application>asterisk</application>
|
||||
</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
<refmiscinfo>asterisk 1.0</refmiscinfo>
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname>
|
||||
<application>asterisk</application>
|
||||
</refname>
|
||||
<refpurpose>
|
||||
All-purpose telephony server.
|
||||
</refpurpose>
|
||||
</refnamediv>
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>asterisk</command>
|
||||
<arg><option>-hfdvVqpRgcin</option></arg>
|
||||
<arg><option>-C </option><replaceable class="parameter">file</replaceable></arg>
|
||||
<arg><option>-U </option><replaceable class="parameter">user</replaceable></arg>
|
||||
<arg><option>-G </option><replaceable class="parameter">group</replaceable></arg>
|
||||
<arg><option>-x </option><replaceable class="parameter">command</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
|
||||
<command>asterisk -r</command>
|
||||
<arg><option>-v</option></arg>
|
||||
<arg><option>-x </option><replaceable class="parameter">command</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
<refsect1>
|
||||
<refsect1info>
|
||||
<date>2004-07-01</date>
|
||||
</refsect1info>
|
||||
<title>DESCRIPTION</title>
|
||||
<para>
|
||||
<command>asterisk</command> is a full-featured telephony server which
|
||||
provides Private Branch eXchange (PBX), Interactive Voice Response (IVR),
|
||||
Automated Call Distribution (ACD), Voice over IP (VoIP) gatewaying,
|
||||
Conferencing, and a plethora of other telephony applications to a broad
|
||||
range of telephony devices including packet voice (SIP, IAX, MGCP, Skinny,
|
||||
H.323) devices (both endpoints and proxies), as well as traditional TDM
|
||||
hardware including T1, E1, ISDN PRI, GR-303, RBS, Loopstart, Groundstart,
|
||||
ISDN BRI, and many more.
|
||||
</para>
|
||||
<para>
|
||||
Asterisk reads most of its configuration files from configuration files
|
||||
located in /etc/asterisk. Virtually all aspects of the operation of
|
||||
asterisk's configuration files can be found in the sample configuration
|
||||
files. The format for those files is generally beyond the scope of this
|
||||
man page.
|
||||
</para>
|
||||
<para>
|
||||
When running with <command>-c</command>, <command>-r</command> or <command>-R</command>
|
||||
options, Asterisk supplies a powerful command line, including command
|
||||
completion, which may be used to monitors its status, perform a variety
|
||||
of administrative actions and even explore the applications that are
|
||||
currently loaded into the system.
|
||||
</para>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>OPTIONS</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>-C <replaceable class="parameter">file</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Use <filename>file</filename> as master configuration file
|
||||
instead of the default, /etc/asterisk/asterisk.conf
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>-c</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Provide a control console on the calling terminal.
|
||||
Specifying this option implies <command>-f</command> and will cause
|
||||
asterisk to no longer fork or detach from the controlling terminal.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>-d</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Enable extra debugging statements.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>-f</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Do not fork or detach from controlling terminal.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>-g</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Remove resource limit on core size, thus forcing Asterisk to dump
|
||||
core in the unlikely event of a segmentation fault or abort signal.
|
||||
<command>NOTE:</command> in some cases this may be incompatible
|
||||
with the <command>-U</command> or <command>-G</command> flags.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>-G <replaceable class="parameter">group</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Run as group <replaceable>group</replaceable> instead of the
|
||||
calling group. <command>NOTE:</command> this requires substantial work
|
||||
to be sure that Asterisk's environment has permission to write
|
||||
the files required for its operation, including logs, its comm
|
||||
socket, the asterisk database, etc.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>-h</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Provide brief summary of command line arguments and terminate.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>-i</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Prompt user to intialize any encrypted private keys during startup.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>-n</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Disable ANSI colors even on terminals capable of displaying them.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>-p</term>
|
||||
<listitem>
|
||||
<para>
|
||||
If supported by the operating system (and executing as root),
|
||||
attempt to run with realtime priority for increased performance and
|
||||
responsiveness within the Asterisk process, at the expense of other
|
||||
programs running on the same machine.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>-q</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Reduce default console output when running in conjunction with
|
||||
console mode (<command>-c</command>).
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>-r</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Instead of running a new Asterisk process, attempt to connect
|
||||
to a running Asterisk process and provide a console interface
|
||||
for controlling it.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>-R</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Much like <command>-r</command>. Instead of running a new Asterisk process, attempt to connect
|
||||
to a running Asterisk process and provide a console interface
|
||||
for controlling it. Additionally, if connection to the Asterisk
|
||||
process is lost, attempt to reconnect for as long as 30 seconds.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>-U <replaceable class="parameter">user</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Run as user <replaceable>user</replaceable> instead of the
|
||||
calling user. <command>NOTE:</command> this requires substantial work
|
||||
to be sure that Asterisk's environment has permission to write
|
||||
the files required for its operation, including logs, its comm
|
||||
socket, the asterisk database, etc.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>-v</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Increase the level of verboseness on the console. The more times
|
||||
<command>-v</command> is specified, the more verbose the output is.
|
||||
Specifying this option implies <command>-f</command> and will cause
|
||||
asterisk to no longer fork or detach from the controlling terminal.
|
||||
This option may also be used in conjunction with <command>-r</command>
|
||||
and <command>-R</command>
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>-V</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Display version information and exit immediately.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>-x <replaceable class="parameter">command</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Connect to a running Asterisk process and execute a command on
|
||||
a command line, passing any output through to standard out and
|
||||
then terminating when the command execution completes. Implies
|
||||
<command>-r</command> when <command>-R</command> is not explicitly
|
||||
supplied.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>EXAMPLES</title>
|
||||
<para>
|
||||
<command>asterisk</command> - Begin Asterisk as a daemon
|
||||
</para>
|
||||
<para>
|
||||
<command>asterisk -vvvgc</command> - Run on controlling terminal
|
||||
</para>
|
||||
<para>
|
||||
<command>asterisk -rx "show channels"</command> - Display channels on running server
|
||||
</para>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>BUGS</title>
|
||||
<para>
|
||||
Bug reports and feature requests may be filed at http://bugs.digium.com
|
||||
</para>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>SEE ALSO</title>
|
||||
<para>
|
||||
*CLI> <command>help</command> - Help on Asterisk CLI
|
||||
</para>
|
||||
<para>
|
||||
*CLI> <command>show applications</command> - Show loaded applications
|
||||
</para>
|
||||
<para>
|
||||
http://www.asterisk.org - The Asterisk Home Page
|
||||
</para>
|
||||
<para>
|
||||
http://www.asteriskdocs.org - The Asterisk Documentation Project
|
||||
</para>
|
||||
<para>
|
||||
http://www.voip-info.org/wiki-Asterisk - The Asterisk Wiki
|
||||
</para>
|
||||
<para>
|
||||
http://www.digium.com/ - Asterisk sponsor and hardware supplier
|
||||
</para>
|
||||
<para>
|
||||
http://www.markocam.com/ - Asterisk author's web cam
|
||||
</para>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>AUTHOR</title>
|
||||
<para>
|
||||
<author>
|
||||
<firstname>Mark Spencer <markster@digium.com></firstname>
|
||||
</author>
|
||||
</para>
|
||||
<para>
|
||||
<author>
|
||||
<firstname>Countless other contributers, see CREDITS with distribution for more information</firstname>
|
||||
</author>
|
||||
</para>
|
||||
</refsect1>
|
||||
</refentry>
|
||||
@@ -2,13 +2,7 @@
|
||||
# Don't use ast mm routines
|
||||
#
|
||||
CFLAGS+=-DNO_AST_MM
|
||||
|
||||
OSARCH=$(shell uname -s)
|
||||
ifeq ($(findstring BSD,${OSARCH}),BSD)
|
||||
CFLAGS+=-I/usr/local/include -L/usr/local/lib
|
||||
endif
|
||||
|
||||
TARGET=$(shell if [ -f /usr/include/newt.h ]; then echo "astman"; else if [ -f /usr/local/include/newt.h ]; then echo "astman"; else echo "none" ; fi ; fi)
|
||||
TARGET=$(shell if [ -f /usr/include/newt.h ]; then echo "astman"; else echo "none" ; fi)
|
||||
all: depend $(TARGET)
|
||||
|
||||
install:
|
||||
@@ -25,7 +19,7 @@ clean:
|
||||
rm -f *.o astman .depend
|
||||
|
||||
astman: astman.o ../md5.o
|
||||
$(CC) $(CFLAGS) -o astman astman.o ../md5.o -lnewt
|
||||
$(CC) -o astman astman.o ../md5.o -lnewt
|
||||
|
||||
ifneq ($(wildcard .depend),)
|
||||
include .depend
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
|
||||
#include <newt.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
@@ -23,8 +23,6 @@
|
||||
#include <asterisk/md5.h>
|
||||
#include <asterisk/manager.h>
|
||||
|
||||
#undef gethostbyname
|
||||
|
||||
#define MAX_HEADERS 80
|
||||
#define MAX_LEN 256
|
||||
|
||||
@@ -172,14 +170,13 @@ static struct event {
|
||||
{ "Status", event_status },
|
||||
{ "Link", event_ignore },
|
||||
{ "Unlink", event_ignore },
|
||||
{ "StatusComplete", event_ignore }
|
||||
};
|
||||
|
||||
static int process_message(struct ast_mansession *s, struct message *m)
|
||||
{
|
||||
int x;
|
||||
char event[80] = "";
|
||||
strncpy(event, get_header(m, "Event"), sizeof(event) - 1);
|
||||
char event[80];
|
||||
strncpy(event, get_header(m, "Event"), sizeof(event));
|
||||
if (!strlen(event)) {
|
||||
fprintf(stderr, "Missing event in request");
|
||||
return 0;
|
||||
@@ -430,7 +427,7 @@ static int get_user_input(char *msg, char *buf, int buflen)
|
||||
newtComponent ok;
|
||||
newtComponent cancel;
|
||||
newtComponent inpfield;
|
||||
const char *input;
|
||||
char *input;
|
||||
int res = -1;
|
||||
struct newtExitStruct es;
|
||||
|
||||
@@ -553,8 +550,8 @@ static int login(char *hostname)
|
||||
newtComponent label;
|
||||
newtComponent ulabel;
|
||||
newtComponent plabel;
|
||||
const char *user;
|
||||
const char *pass;
|
||||
char *user;
|
||||
char *pass;
|
||||
struct message *m;
|
||||
struct newtExitStruct es;
|
||||
char tmp[55];
|
||||
|
||||
5
astmm.c
5
astmm.c
@@ -18,6 +18,7 @@
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
#include <asterisk/cli.h>
|
||||
#include <asterisk/logger.h>
|
||||
@@ -57,8 +58,8 @@ static struct ast_region {
|
||||
#define HASH(a) \
|
||||
(((unsigned long)(a)) % SOME_PRIME)
|
||||
|
||||
AST_MUTEX_DEFINE_STATIC(reglock);
|
||||
AST_MUTEX_DEFINE_STATIC(showmemorylock);
|
||||
static ast_mutex_t reglock = AST_MUTEX_INITIALIZER;
|
||||
static ast_mutex_t showmemorylock = AST_MUTEX_INITIALIZER;
|
||||
|
||||
static inline void *__ast_alloc_region(size_t size, int which, const char *file, int lineno, const char *func)
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
@@ -32,12 +33,10 @@
|
||||
#include <asterisk/chanvars.h>
|
||||
#include <asterisk/linkedlists.h>
|
||||
#include <asterisk/indications.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/utils.h>
|
||||
|
||||
#define MAX_AUTOMONS 256
|
||||
|
||||
AST_MUTEX_DEFINE_STATIC(autolock);
|
||||
static ast_mutex_t autolock = AST_MUTEX_INITIALIZER;
|
||||
|
||||
struct asent {
|
||||
struct ast_channel *chan;
|
||||
@@ -45,7 +44,7 @@ struct asent {
|
||||
};
|
||||
|
||||
static struct asent *aslist = NULL;
|
||||
static pthread_t asthread = AST_PTHREADT_NULL;
|
||||
static pthread_t asthread = (pthread_t) -1;
|
||||
|
||||
static void *autoservice_run(void *ign)
|
||||
{
|
||||
@@ -81,7 +80,7 @@ static void *autoservice_run(void *ign)
|
||||
ast_frfree(f);
|
||||
}
|
||||
}
|
||||
asthread = AST_PTHREADT_NULL;
|
||||
asthread = (pthread_t) -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -91,7 +90,7 @@ int ast_autoservice_start(struct ast_channel *chan)
|
||||
struct asent *as;
|
||||
int needstart;
|
||||
ast_mutex_lock(&autolock);
|
||||
needstart = (asthread == AST_PTHREADT_NULL) ? 1 : 0 /* aslist ? 0 : 1 */;
|
||||
needstart = (asthread == (pthread_t) -1) ? 1 : 0 /* aslist ? 0 : 1 */;
|
||||
as = aslist;
|
||||
while(as) {
|
||||
if (as->chan == chan)
|
||||
@@ -107,7 +106,7 @@ int ast_autoservice_start(struct ast_channel *chan)
|
||||
aslist = as;
|
||||
res = 0;
|
||||
if (needstart) {
|
||||
if (ast_pthread_create(&asthread, NULL, autoservice_run, NULL)) {
|
||||
if (pthread_create(&asthread, NULL, autoservice_run, NULL)) {
|
||||
ast_log(LOG_WARNING, "Unable to create autoservice thread :(\n");
|
||||
free(aslist);
|
||||
aslist = NULL;
|
||||
@@ -143,7 +142,7 @@ int ast_autoservice_stop(struct ast_channel *chan)
|
||||
if (!chan->_softhangup)
|
||||
res = 0;
|
||||
}
|
||||
if (asthread != AST_PTHREADT_NULL)
|
||||
if (asthread != (pthread_t) -1)
|
||||
pthread_kill(asthread, SIGURG);
|
||||
ast_mutex_unlock(&autolock);
|
||||
/* Wait for it to un-block */
|
||||
|
||||
115
callerid.c
115
callerid.c
@@ -3,9 +3,9 @@
|
||||
*
|
||||
* CallerID Generation support
|
||||
*
|
||||
* Copyright (C) 2001-2004, Digium, Inc.
|
||||
* Copyright (C) 2001, Linux Support Services, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License.
|
||||
@@ -20,14 +20,12 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <ctype.h>
|
||||
#include <asterisk/ulaw.h>
|
||||
#include <asterisk/alaw.h>
|
||||
#include <asterisk/frame.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/fskmodem.h>
|
||||
#include <asterisk/utils.h>
|
||||
|
||||
struct callerid_state {
|
||||
fsk_data fskd;
|
||||
@@ -74,7 +72,7 @@ static inline void gen_tones(unsigned char *buf, int len, int codec, float ddr1,
|
||||
t = 2.0 - (*cr2 * *cr2 + *ci2 * *ci2);
|
||||
*cr2 *= t;
|
||||
*ci2 *= t;
|
||||
buf[x] = AST_LIN2X((*cr1 + *cr2) * 2048.0);
|
||||
buf[x] = AST_LIN2X((*cr1 + *cr2) * 8192.0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +106,7 @@ void callerid_init(void)
|
||||
casdi2 = sin(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
|
||||
}
|
||||
|
||||
struct callerid_state *callerid_new(int cid_signalling)
|
||||
struct callerid_state *callerid_new(void)
|
||||
{
|
||||
struct callerid_state *cid;
|
||||
cid = malloc(sizeof(struct callerid_state));
|
||||
@@ -120,13 +118,8 @@ struct callerid_state *callerid_new(int cid_signalling)
|
||||
cid->fskd.nstop = 1; /* 1 stop bit */
|
||||
cid->fskd.paridad = 0; /* No parity */
|
||||
cid->fskd.bw=1; /* Filter 800 Hz */
|
||||
if (cid_signalling == 2) { /* v23 signalling */
|
||||
cid->fskd.f_mark_idx = 4; /* 1300 Hz */
|
||||
cid->fskd.f_space_idx = 5; /* 2100 Hz */
|
||||
} else { /* Bell 202 signalling as default */
|
||||
cid->fskd.f_mark_idx = 2; /* 1200 Hz */
|
||||
cid->fskd.f_space_idx = 3; /* 2200 Hz */
|
||||
}
|
||||
cid->fskd.f_mark_idx = 2; /* 1200 Hz */
|
||||
cid->fskd.f_space_idx = 3; /* 2200 Hz */
|
||||
cid->fskd.pcola = 0; /* No clue */
|
||||
cid->fskd.cont = 0; /* Digital PLL reset */
|
||||
cid->fskd.x0 = 0.0;
|
||||
@@ -153,67 +146,6 @@ void callerid_get(struct callerid_state *cid, char **name, char **number, int *f
|
||||
*number = cid->number;
|
||||
}
|
||||
|
||||
void callerid_get_dtmf(char *cidstring, char *number, int *flags)
|
||||
{
|
||||
int i;
|
||||
int code;
|
||||
|
||||
/* "Clear" the number-buffer. */
|
||||
number[0] = 0;
|
||||
|
||||
if (strlen(cidstring) < 2) {
|
||||
ast_log(LOG_DEBUG, "No cid detected\n");
|
||||
*flags = CID_UNKNOWN_NUMBER;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Detect protocol and special types */
|
||||
if (cidstring[0] == 'B') {
|
||||
/* Handle special codes */
|
||||
code = atoi(&cidstring[1]);
|
||||
if (code == 0)
|
||||
*flags = CID_UNKNOWN_NUMBER;
|
||||
else if (code == 10)
|
||||
*flags = CID_PRIVATE_NUMBER;
|
||||
else
|
||||
ast_log(LOG_DEBUG, "Unknown DTMF code %d\n", code);
|
||||
} else if (cidstring[0] == 'D' && cidstring[2] == '#') {
|
||||
/* .DK special code */
|
||||
if (cidstring[1] == '1')
|
||||
*flags = CID_PRIVATE_NUMBER;
|
||||
if (cidstring[1] == '2' || cidstring[1] == '3')
|
||||
*flags = CID_UNKNOWN_NUMBER;
|
||||
} else if (cidstring[0] == 'D' || cidstring[0] == 'A') {
|
||||
/* "Standard" callerid */
|
||||
for (i = 1; i < strlen(cidstring); i++ ) {
|
||||
if (cidstring[i] == 'C' || cidstring[i] == '#')
|
||||
break;
|
||||
if (isdigit(cidstring[i]))
|
||||
number[i-1] = cidstring[i];
|
||||
else
|
||||
ast_log(LOG_DEBUG, "Unknown CID digit '%c'\n",
|
||||
cidstring[i]);
|
||||
}
|
||||
number[i-1] = 0;
|
||||
} else if (isdigit(cidstring[0])) {
|
||||
/* It begins with a digit, so we parse it as a number and hope
|
||||
* for the best */
|
||||
ast_log(LOG_WARNING, "Couldn't detect start-character. CID "
|
||||
"parsing might be unreliable\n");
|
||||
for (i = 0; i < strlen(cidstring); i++) {
|
||||
if (isdigit(cidstring[i]))
|
||||
number[i] = cidstring[i];
|
||||
else
|
||||
break;
|
||||
}
|
||||
number[i] = 0;
|
||||
} else {
|
||||
ast_log(LOG_DEBUG, "Unknown CID protocol, start digit '%c'\n",
|
||||
cidstring[0]);
|
||||
*flags = CID_UNKNOWN_NUMBER;
|
||||
}
|
||||
}
|
||||
|
||||
int ast_gen_cas(unsigned char *outbuf, int sendsas, int len, int codec)
|
||||
{
|
||||
int pos = 0;
|
||||
@@ -253,7 +185,7 @@ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int
|
||||
mylen += cid->oldlen/2;
|
||||
for (x=0;x<len;x++)
|
||||
buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
|
||||
while(mylen >= 160) {
|
||||
while(mylen >= 80) {
|
||||
olen = mylen;
|
||||
res = fsk_serie(&cid->fskd, buf, &mylen, &b);
|
||||
if (mylen < 0) {
|
||||
@@ -309,8 +241,8 @@ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int
|
||||
break;
|
||||
}
|
||||
|
||||
cid->number[0] = '\0';
|
||||
cid->name[0] = '\0';
|
||||
strcpy(cid->number, "");
|
||||
strcpy(cid->name, "");
|
||||
/* If we get this far we're fine. */
|
||||
if (cid->type == 0x80) {
|
||||
/* MDMF */
|
||||
@@ -328,13 +260,9 @@ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int
|
||||
ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]);
|
||||
res = 32;
|
||||
}
|
||||
if (ast_strlen_zero(cid->number)) {
|
||||
memcpy(cid->number, cid->rawdata + x + 1, res);
|
||||
/* Null terminate */
|
||||
cid->number[res] = '\0';
|
||||
}
|
||||
break;
|
||||
case 6: /* Stentor Call Qualifier (ie. Long Distance call) */
|
||||
memcpy(cid->number, cid->rawdata + x + 1, res);
|
||||
/* Null terminate */
|
||||
cid->number[res] = '\0';
|
||||
break;
|
||||
case 7: /* Name */
|
||||
case 8: /* Name */
|
||||
@@ -346,8 +274,6 @@ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int
|
||||
memcpy(cid->name, cid->rawdata + x + 1, res);
|
||||
cid->name[res] = '\0';
|
||||
break;
|
||||
case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting */
|
||||
case 19: /* UK: Network message system status (Number of messages waiting) */
|
||||
case 22: /* Something French */
|
||||
break;
|
||||
default:
|
||||
@@ -365,14 +291,14 @@ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int
|
||||
if (!strcmp(cid->number, "P")) {
|
||||
strcpy(cid->number, "");
|
||||
cid->flags |= CID_PRIVATE_NUMBER;
|
||||
} else if (!strcmp(cid->number, "O") || ast_strlen_zero(cid->number)) {
|
||||
} else if (!strcmp(cid->number, "O") || !strlen(cid->number)) {
|
||||
strcpy(cid->number, "");
|
||||
cid->flags |= CID_UNKNOWN_NUMBER;
|
||||
}
|
||||
if (!strcmp(cid->name, "P")) {
|
||||
strcpy(cid->name, "");
|
||||
cid->flags |= CID_PRIVATE_NAME;
|
||||
} else if (!strcmp(cid->name, "O") || ast_strlen_zero(cid->name)) {
|
||||
} else if (!strcmp(cid->name, "O") || !strlen(cid->name)) {
|
||||
strcpy(cid->name, "");
|
||||
cid->flags |= CID_UNKNOWN_NAME;
|
||||
}
|
||||
@@ -415,7 +341,7 @@ static int callerid_genmsg(char *msg, int size, char *number, char *name, int fl
|
||||
tm.tm_mday, tm.tm_hour, tm.tm_min);
|
||||
size -= res;
|
||||
ptr += res;
|
||||
if (!number || ast_strlen_zero(number) || (flags & CID_UNKNOWN_NUMBER)) {
|
||||
if (!number || !strlen(number) || (flags & CID_UNKNOWN_NUMBER)) {
|
||||
/* Indicate number not known */
|
||||
res = snprintf(ptr, size, "\004\001O");
|
||||
size -= res;
|
||||
@@ -439,7 +365,7 @@ static int callerid_genmsg(char *msg, int size, char *number, char *name, int fl
|
||||
size -= i;
|
||||
}
|
||||
|
||||
if (!name || ast_strlen_zero(name) || (flags & CID_UNKNOWN_NAME)) {
|
||||
if (!name || !strlen(name) || (flags & CID_UNKNOWN_NAME)) {
|
||||
/* Indicate name not known */
|
||||
res = snprintf(ptr, size, "\010\001O");
|
||||
size -= res;
|
||||
@@ -510,9 +436,6 @@ int vmwi_generate(unsigned char *buf, int active, int mdmf, int codec)
|
||||
sum += msg[x];
|
||||
sum = (256 - (sum & 255));
|
||||
msg[len++] = sum;
|
||||
/* Wait a half a second */
|
||||
for (x=0;x<4000;x++)
|
||||
PUT_BYTE(0x7f);
|
||||
/* Transmit 30 0x55's (looks like a square wave) for channel seizure */
|
||||
for (x=0;x<30;x++)
|
||||
PUT_CLID(0x55);
|
||||
@@ -582,10 +505,10 @@ void ast_shrink_phone_number(char *n)
|
||||
int ast_isphonenumber(char *n)
|
||||
{
|
||||
int x;
|
||||
if (!n || ast_strlen_zero(n))
|
||||
if (!n || !strlen(n))
|
||||
return 0;
|
||||
for (x=0;n[x];x++)
|
||||
if (!strchr("0123456789*#+", n[x]))
|
||||
if (!strchr("0123456789*#", n[x]))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -611,7 +534,7 @@ int ast_callerid_parse(char *instr, char **name, char **location)
|
||||
} else {
|
||||
/* Just trim off any trailing spaces */
|
||||
*name = instr;
|
||||
while(!ast_strlen_zero(instr) && (instr[strlen(instr) - 1] < 33))
|
||||
while(strlen(instr) && (instr[strlen(instr) - 1] < 33))
|
||||
instr[strlen(instr) - 1] = '\0';
|
||||
/* And leading spaces */
|
||||
while(**name && (**name < 33))
|
||||
|
||||
354
cdr.c
354
cdr.c
@@ -3,9 +3,9 @@
|
||||
*
|
||||
* Call Detail Record API
|
||||
*
|
||||
* Copyright (C) 1999-2004, Digium, Inc.
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License.
|
||||
@@ -20,16 +20,15 @@
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <asterisk/causes.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
int ast_default_amaflags = AST_CDR_DOCUMENTATION;
|
||||
char ast_default_accountcode[20] = "";
|
||||
|
||||
AST_MUTEX_DEFINE_STATIC(cdrlock);
|
||||
static ast_mutex_t cdrlock = AST_MUTEX_INITIALIZER;
|
||||
|
||||
static struct ast_cdr_beitem {
|
||||
char name[20];
|
||||
@@ -38,7 +37,6 @@ static struct ast_cdr_beitem {
|
||||
struct ast_cdr_beitem *next;
|
||||
} *bes = NULL;
|
||||
|
||||
|
||||
/*
|
||||
* We do a lot of checking here in the CDR code to try to be sure we don't ever let a CDR slip
|
||||
* through our fingers somehow. If someone allocates a CDR, it must be completely handled normally
|
||||
@@ -96,8 +94,6 @@ void ast_cdr_unregister(char *name)
|
||||
}
|
||||
i = i->next;
|
||||
}
|
||||
if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Unregistered '%s' CDR backend\n", name);
|
||||
ast_mutex_unlock(&cdrlock);
|
||||
if (i)
|
||||
free(i);
|
||||
@@ -105,19 +101,16 @@ void ast_cdr_unregister(char *name)
|
||||
|
||||
void ast_cdr_free(struct ast_cdr *cdr)
|
||||
{
|
||||
char *chan;
|
||||
struct ast_cdr *next;
|
||||
while (cdr) {
|
||||
next = cdr->next;
|
||||
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (!ast_cdr_has_flag(cdr,AST_CDR_FLAG_POSTED))
|
||||
char *chan;
|
||||
if (cdr) {
|
||||
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (!cdr->posted)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' not posted\n", chan);
|
||||
if (!cdr->end.tv_sec && !cdr->end.tv_usec)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' lacks end\n", chan);
|
||||
if (!cdr->start.tv_sec && !cdr->start.tv_usec)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' lacks start\n", chan);
|
||||
free(cdr);
|
||||
cdr = next;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,67 +127,58 @@ struct ast_cdr *ast_cdr_alloc(void)
|
||||
void ast_cdr_start(struct ast_cdr *cdr)
|
||||
{
|
||||
char *chan;
|
||||
while (cdr) {
|
||||
if (!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED)) {
|
||||
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (ast_cdr_has_flag(cdr,AST_CDR_FLAG_POSTED))
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
|
||||
if (cdr->start.tv_sec || cdr->start.tv_usec)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already started\n", chan);
|
||||
gettimeofday(&cdr->start, NULL);
|
||||
}
|
||||
cdr = cdr->next;
|
||||
if (cdr) {
|
||||
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (cdr->posted)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
|
||||
if (cdr->start.tv_sec || cdr->start.tv_usec)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already started\n", chan);
|
||||
gettimeofday(&cdr->start, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void ast_cdr_answer(struct ast_cdr *cdr)
|
||||
{
|
||||
char *chan;
|
||||
while (cdr) {
|
||||
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (ast_cdr_has_flag(cdr,AST_CDR_FLAG_POSTED))
|
||||
if (cdr) {
|
||||
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (cdr->posted)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
|
||||
if (cdr->disposition < AST_CDR_ANSWERED)
|
||||
cdr->disposition = AST_CDR_ANSWERED;
|
||||
if (!cdr->answer.tv_sec && !cdr->answer.tv_usec) {
|
||||
gettimeofday(&cdr->answer, NULL);
|
||||
}
|
||||
cdr = cdr->next;
|
||||
}
|
||||
}
|
||||
|
||||
void ast_cdr_busy(struct ast_cdr *cdr)
|
||||
{
|
||||
char *chan;
|
||||
while (cdr) {
|
||||
if (!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED)) {
|
||||
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (ast_cdr_has_flag(cdr,AST_CDR_FLAG_POSTED))
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
|
||||
if (cdr->disposition < AST_CDR_BUSY)
|
||||
cdr->disposition = AST_CDR_BUSY;
|
||||
}
|
||||
cdr = cdr->next;
|
||||
if (cdr) {
|
||||
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (cdr->posted)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
|
||||
if (cdr->disposition < AST_CDR_BUSY)
|
||||
cdr->disposition = AST_CDR_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
void ast_cdr_failed(struct ast_cdr *cdr)
|
||||
{
|
||||
char *chan;
|
||||
while (cdr) {
|
||||
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (ast_cdr_has_flag(cdr,AST_CDR_FLAG_POSTED))
|
||||
if (cdr) {
|
||||
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (cdr->posted)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
|
||||
if(!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED))
|
||||
cdr->disposition = AST_CDR_FAILED;
|
||||
cdr = cdr->next;
|
||||
}
|
||||
}
|
||||
|
||||
int ast_cdr_disposition(struct ast_cdr *cdr, int cause)
|
||||
{
|
||||
int res = 0;
|
||||
while (cdr) {
|
||||
if (cdr) {
|
||||
switch(cause) {
|
||||
case AST_CAUSE_BUSY:
|
||||
ast_cdr_busy(cdr);
|
||||
@@ -211,7 +195,6 @@ int ast_cdr_disposition(struct ast_cdr *cdr, int cause)
|
||||
res = -1;
|
||||
ast_log(LOG_WARNING, "We don't handle that cause yet\n");
|
||||
}
|
||||
cdr = cdr->next;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -219,32 +202,27 @@ int ast_cdr_disposition(struct ast_cdr *cdr, int cause)
|
||||
void ast_cdr_setdestchan(struct ast_cdr *cdr, char *chann)
|
||||
{
|
||||
char *chan;
|
||||
while (cdr) {
|
||||
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (ast_cdr_has_flag(cdr,AST_CDR_FLAG_POSTED))
|
||||
if (cdr) {
|
||||
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (cdr->posted)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
|
||||
if(!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED))
|
||||
strncpy(cdr->dstchannel, chann, sizeof(cdr->dstchannel) - 1);
|
||||
cdr = cdr->next;
|
||||
strncpy(cdr->dstchannel, chann, sizeof(cdr->dstchannel) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ast_cdr_setapp(struct ast_cdr *cdr, char *app, char *data)
|
||||
{
|
||||
char *chan;
|
||||
while (cdr) {
|
||||
if(!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED)) {
|
||||
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (ast_cdr_has_flag(cdr,AST_CDR_FLAG_POSTED))
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
|
||||
if (!app)
|
||||
app = "";
|
||||
strncpy(cdr->lastapp, app, sizeof(cdr->lastapp) - 1);
|
||||
if (!data)
|
||||
data = "";
|
||||
strncpy(cdr->lastdata, data, sizeof(cdr->lastdata) - 1);
|
||||
}
|
||||
cdr = cdr->next;
|
||||
if (cdr) {
|
||||
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (cdr->posted)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
|
||||
if (!app)
|
||||
app = "";
|
||||
strncpy(cdr->lastapp, app, sizeof(cdr->lastapp) - 1);
|
||||
if (!data)
|
||||
data = "";
|
||||
strncpy(cdr->lastdata, data, sizeof(cdr->lastdata) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,24 +230,21 @@ int ast_cdr_setcid(struct ast_cdr *cdr, struct ast_channel *c)
|
||||
{
|
||||
char tmp[AST_MAX_EXTENSION] = "";
|
||||
char *num, *name;
|
||||
while (cdr) {
|
||||
if(!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED)) {
|
||||
/* Grab source from ANI or normal Caller*ID */
|
||||
if (c->ani)
|
||||
strncpy(tmp, c->ani, sizeof(tmp) - 1);
|
||||
else if (c->callerid)
|
||||
strncpy(tmp, c->callerid, sizeof(tmp) - 1);
|
||||
if (c->callerid)
|
||||
strncpy(cdr->clid, c->callerid, sizeof(cdr->clid) - 1);
|
||||
name = NULL;
|
||||
num = NULL;
|
||||
ast_callerid_parse(tmp, &name, &num);
|
||||
if (num) {
|
||||
ast_shrink_phone_number(num);
|
||||
strncpy(cdr->src, num, sizeof(cdr->src) - 1);
|
||||
}
|
||||
if (cdr) {
|
||||
/* Grab source from ANI or normal Caller*ID */
|
||||
if (c->ani)
|
||||
strncpy(tmp, c->ani, sizeof(tmp) - 1);
|
||||
else if (c->callerid)
|
||||
strncpy(tmp, c->callerid, sizeof(tmp) - 1);
|
||||
if (c->callerid)
|
||||
strncpy(cdr->clid, c->callerid, sizeof(cdr->clid) - 1);
|
||||
name = NULL;
|
||||
num = NULL;
|
||||
ast_callerid_parse(tmp, &name, &num);
|
||||
if (num) {
|
||||
ast_shrink_phone_number(num);
|
||||
strncpy(cdr->src, num, sizeof(cdr->src) - 1);
|
||||
}
|
||||
cdr = cdr->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -279,43 +254,40 @@ int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *c)
|
||||
char *chan;
|
||||
char *num, *name;
|
||||
char tmp[AST_MAX_EXTENSION] = "";
|
||||
while (cdr) {
|
||||
if(!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED)) {
|
||||
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (!ast_strlen_zero(cdr->channel))
|
||||
ast_log(LOG_WARNING, "CDR already initialized on '%s'\n", chan);
|
||||
strncpy(cdr->channel, c->name, sizeof(cdr->channel) - 1);
|
||||
/* Grab source from ANI or normal Caller*ID */
|
||||
if (c->ani)
|
||||
strncpy(tmp, c->ani, sizeof(tmp) - 1);
|
||||
else if (c->callerid)
|
||||
strncpy(tmp, c->callerid, sizeof(tmp) - 1);
|
||||
if (c->callerid)
|
||||
strncpy(cdr->clid, c->callerid, sizeof(cdr->clid) - 1);
|
||||
name = NULL;
|
||||
num = NULL;
|
||||
ast_callerid_parse(tmp, &name, &num);
|
||||
if (num) {
|
||||
ast_shrink_phone_number(num);
|
||||
strncpy(cdr->src, num, sizeof(cdr->src) - 1);
|
||||
}
|
||||
|
||||
if (c->_state == AST_STATE_UP)
|
||||
cdr->disposition = AST_CDR_ANSWERED;
|
||||
else
|
||||
cdr->disposition = AST_CDR_NOANSWER;
|
||||
if (c->amaflags)
|
||||
cdr->amaflags = c->amaflags;
|
||||
else
|
||||
cdr->amaflags = ast_default_amaflags;
|
||||
strncpy(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode) - 1);
|
||||
/* Destination information */
|
||||
strncpy(cdr->dst, c->exten, sizeof(cdr->dst) - 1);
|
||||
strncpy(cdr->dcontext, c->context, sizeof(cdr->dcontext) - 1);
|
||||
/* Unique call identifier */
|
||||
strncpy(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid) - 1);
|
||||
if (cdr) {
|
||||
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (strlen(cdr->channel))
|
||||
ast_log(LOG_WARNING, "CDR already initialized on '%s'\n", chan);
|
||||
strncpy(cdr->channel, c->name, sizeof(cdr->channel) - 1);
|
||||
/* Grab source from ANI or normal Caller*ID */
|
||||
if (c->ani)
|
||||
strncpy(tmp, c->ani, sizeof(tmp) - 1);
|
||||
else if (c->callerid)
|
||||
strncpy(tmp, c->callerid, sizeof(tmp) - 1);
|
||||
if (c->callerid)
|
||||
strncpy(cdr->clid, c->callerid, sizeof(cdr->clid) - 1);
|
||||
name = NULL;
|
||||
num = NULL;
|
||||
ast_callerid_parse(tmp, &name, &num);
|
||||
if (num) {
|
||||
ast_shrink_phone_number(num);
|
||||
strncpy(cdr->src, num, sizeof(cdr->src) - 1);
|
||||
}
|
||||
cdr = cdr->next;
|
||||
|
||||
if (c->_state == AST_STATE_UP)
|
||||
cdr->disposition = AST_CDR_ANSWERED;
|
||||
else
|
||||
cdr->disposition = AST_CDR_NOANSWER;
|
||||
if (c->amaflags)
|
||||
cdr->amaflags = c->amaflags;
|
||||
else
|
||||
cdr->amaflags = ast_default_amaflags;
|
||||
strncpy(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode) - 1);
|
||||
/* Destination information */
|
||||
strncpy(cdr->dst, c->exten, sizeof(cdr->dst) - 1);
|
||||
strncpy(cdr->dcontext, c->context, sizeof(cdr->dcontext) - 1);
|
||||
/* Unique call identifier */
|
||||
strncpy(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid) - 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -323,15 +295,14 @@ int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *c)
|
||||
void ast_cdr_end(struct ast_cdr *cdr)
|
||||
{
|
||||
char *chan;
|
||||
while (cdr) {
|
||||
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (ast_cdr_has_flag(cdr,AST_CDR_FLAG_POSTED))
|
||||
if (cdr) {
|
||||
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (cdr->posted)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
|
||||
if (!cdr->start.tv_sec && !cdr->start.tv_usec)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", chan);
|
||||
if (!cdr->end.tv_sec && !cdr->end.tv_usec)
|
||||
gettimeofday(&cdr->end, NULL);
|
||||
cdr = cdr->next;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,23 +340,8 @@ int ast_cdr_setaccount(struct ast_channel *chan, char *account)
|
||||
struct ast_cdr *cdr = chan->cdr;
|
||||
|
||||
strncpy(chan->accountcode, account, sizeof(chan->accountcode) - 1);
|
||||
while (cdr) {
|
||||
if(!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED))
|
||||
strncpy(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode) - 1);
|
||||
cdr = cdr->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ast_cdr_setamaflags(struct ast_channel *chan, char *flag)
|
||||
{
|
||||
struct ast_cdr *cdr = chan->cdr;
|
||||
int newflag;
|
||||
|
||||
newflag = ast_cdr_amaflags2int(flag);
|
||||
if (newflag) {
|
||||
cdr->amaflags = newflag;
|
||||
}
|
||||
if (cdr)
|
||||
strncpy(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode) - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -393,11 +349,8 @@ int ast_cdr_setuserfield(struct ast_channel *chan, char *userfield)
|
||||
{
|
||||
struct ast_cdr *cdr = chan->cdr;
|
||||
|
||||
while (cdr) {
|
||||
if(!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED))
|
||||
strncpy(cdr->userfield, userfield, sizeof(cdr->userfield) - 1);
|
||||
cdr = cdr->next;
|
||||
}
|
||||
if (cdr)
|
||||
strncpy(cdr->userfield, userfield, sizeof(cdr->userfield) - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -405,13 +358,10 @@ int ast_cdr_appenduserfield(struct ast_channel *chan, char *userfield)
|
||||
{
|
||||
struct ast_cdr *cdr = chan->cdr;
|
||||
|
||||
while (cdr)
|
||||
if (cdr)
|
||||
{
|
||||
|
||||
int len = strlen(cdr->userfield);
|
||||
if(!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED))
|
||||
strncpy(cdr->userfield+len, userfield, sizeof(cdr->userfield) - len - 1);
|
||||
cdr = cdr->next;
|
||||
strncpy(cdr->userfield+len, userfield, sizeof(cdr->userfield) - len - 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -422,38 +372,28 @@ int ast_cdr_update(struct ast_channel *c)
|
||||
char *name, *num;
|
||||
char tmp[AST_MAX_EXTENSION] = "";
|
||||
/* Grab source from ANI or normal Caller*ID */
|
||||
while (cdr) {
|
||||
if(!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED)) {
|
||||
if (c->ani)
|
||||
strncpy(tmp, c->ani, sizeof(tmp) - 1);
|
||||
else if (c->callerid && !ast_strlen_zero(c->callerid))
|
||||
strncpy(tmp, c->callerid, sizeof(tmp) - 1);
|
||||
if (c->callerid && !ast_strlen_zero(c->callerid))
|
||||
strncpy(cdr->clid, c->callerid, sizeof(cdr->clid) - 1);
|
||||
else
|
||||
cdr->clid[0] = '\0';
|
||||
name = NULL;
|
||||
num = NULL;
|
||||
ast_callerid_parse(tmp, &name, &num);
|
||||
if (num) {
|
||||
ast_shrink_phone_number(num);
|
||||
strncpy(cdr->src, num, sizeof(cdr->src) - 1);
|
||||
}
|
||||
/* Copy account code et-al */
|
||||
strncpy(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode) - 1);
|
||||
/* Destination information */
|
||||
if (ast_strlen_zero(c->macroexten))
|
||||
strncpy(cdr->dst, c->exten, sizeof(cdr->dst) - 1);
|
||||
else
|
||||
strncpy(cdr->dst, c->macroexten, sizeof(cdr->dst) - 1);
|
||||
if (ast_strlen_zero(c->macrocontext))
|
||||
strncpy(cdr->dcontext, c->context, sizeof(cdr->dcontext) - 1);
|
||||
else
|
||||
strncpy(cdr->dcontext, c->macrocontext, sizeof(cdr->dcontext) - 1);
|
||||
if (cdr) {
|
||||
if (c->ani)
|
||||
strncpy(tmp, c->ani, sizeof(tmp) - 1);
|
||||
else if (c->callerid && strlen(c->callerid))
|
||||
strncpy(tmp, c->callerid, sizeof(tmp) - 1);
|
||||
if (c->callerid && strlen(c->callerid))
|
||||
strncpy(cdr->clid, c->callerid, sizeof(cdr->clid) - 1);
|
||||
else
|
||||
strcpy(cdr->clid, "");
|
||||
name = NULL;
|
||||
num = NULL;
|
||||
ast_callerid_parse(tmp, &name, &num);
|
||||
if (num) {
|
||||
ast_shrink_phone_number(num);
|
||||
strncpy(cdr->src, num, sizeof(cdr->src) - 1);
|
||||
}
|
||||
cdr = cdr->next;
|
||||
/* Copy account code et-al */
|
||||
strncpy(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode) - 1);
|
||||
/* Destination information */
|
||||
strncpy(cdr->dst, c->exten, sizeof(cdr->dst) - 1);
|
||||
strncpy(cdr->dcontext, c->context, sizeof(cdr->dcontext) - 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -474,9 +414,9 @@ void ast_cdr_post(struct ast_cdr *cdr)
|
||||
{
|
||||
char *chan;
|
||||
struct ast_cdr_beitem *i;
|
||||
while (cdr) {
|
||||
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (ast_cdr_has_flag(cdr,AST_CDR_FLAG_POSTED))
|
||||
if (cdr) {
|
||||
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
|
||||
if (cdr->posted)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
|
||||
if (!cdr->end.tv_sec && !cdr->end.tv_usec)
|
||||
ast_log(LOG_WARNING, "CDR on channel '%s' lacks end\n", chan);
|
||||
@@ -487,7 +427,7 @@ void ast_cdr_post(struct ast_cdr *cdr)
|
||||
cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec + (cdr->end.tv_usec - cdr->answer.tv_usec) / 1000000;
|
||||
} else
|
||||
cdr->billsec = 0;
|
||||
ast_cdr_add_flag(cdr,AST_CDR_FLAG_POSTED);
|
||||
cdr->posted = 1;
|
||||
ast_mutex_lock(&cdrlock);
|
||||
i = bes;
|
||||
while(i) {
|
||||
@@ -495,45 +435,25 @@ void ast_cdr_post(struct ast_cdr *cdr)
|
||||
i = i->next;
|
||||
}
|
||||
ast_mutex_unlock(&cdrlock);
|
||||
cdr = cdr->next;
|
||||
}
|
||||
}
|
||||
|
||||
void ast_cdr_reset(struct ast_cdr *cdr, int flags)
|
||||
void ast_cdr_reset(struct ast_cdr *cdr, int post)
|
||||
{
|
||||
while (cdr) {
|
||||
/* Post if requested */
|
||||
if (ast_cdr_compare_flag(flags,AST_CDR_FLAG_LOCKED) || !ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED)) {
|
||||
if (ast_cdr_compare_flag(flags,AST_CDR_FLAG_POSTED)) {
|
||||
ast_cdr_end(cdr);
|
||||
ast_cdr_post(cdr);
|
||||
}
|
||||
/* Reset to initial state */
|
||||
cdr->flags=0;
|
||||
memset(&cdr->start, 0, sizeof(cdr->start));
|
||||
memset(&cdr->end, 0, sizeof(cdr->end));
|
||||
memset(&cdr->answer, 0, sizeof(cdr->answer));
|
||||
cdr->billsec = 0;
|
||||
cdr->duration = 0;
|
||||
ast_cdr_start(cdr);
|
||||
cdr->disposition = AST_CDR_NOANSWER;
|
||||
}
|
||||
|
||||
cdr = cdr->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct ast_cdr *ast_cdr_append(struct ast_cdr *cdr, struct ast_cdr *newcdr)
|
||||
{
|
||||
struct ast_cdr *ret;
|
||||
if (cdr) {
|
||||
ret = cdr;
|
||||
while(cdr->next)
|
||||
cdr = cdr->next;
|
||||
cdr->next = newcdr;
|
||||
} else {
|
||||
ret = newcdr;
|
||||
/* Post if requested */
|
||||
if (post) {
|
||||
ast_cdr_end(cdr);
|
||||
ast_cdr_post(cdr);
|
||||
}
|
||||
/* Reset to initial state */
|
||||
cdr->posted = 0;
|
||||
memset(&cdr->start, 0, sizeof(cdr->start));
|
||||
memset(&cdr->end, 0, sizeof(cdr->end));
|
||||
memset(&cdr->answer, 0, sizeof(cdr->answer));
|
||||
cdr->billsec = 0;
|
||||
cdr->duration = 0;
|
||||
ast_cdr_start(cdr);
|
||||
cdr->disposition = AST_CDR_NOANSWER;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
38
cdr/Makefile
38
cdr/Makefile
@@ -12,40 +12,17 @@
|
||||
#
|
||||
|
||||
#ADD cdr_pgsql.so to MODS= to include PostgreSQL support: REQUIRES PostgreSQL libs
|
||||
MODS=cdr_csv.so cdr_manager.so
|
||||
MODS=cdr_csv.so
|
||||
|
||||
|
||||
CFLAGS+=-fPIC
|
||||
|
||||
PROC=$(shell uname -m)
|
||||
OSARCH=$(shell uname -s)
|
||||
|
||||
ifeq (${OSARCH},FreeBSD)
|
||||
SOLINK+=-L/usr/local/lib
|
||||
endif
|
||||
|
||||
#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
|
||||
ifeq ($(PROC),sparc64)
|
||||
PROC=ultrasparc
|
||||
CFLAGS += -mtune=$(PROC) -O3 -pipe -fomit-frame-pointer -mcpu=v8
|
||||
endif
|
||||
|
||||
#
|
||||
# unixODBC stuff...
|
||||
#
|
||||
MODS+=$(shell if [ -f "/usr/include/odbcinst.h" ]; then echo "cdr_odbc.so"; fi)
|
||||
MODS+=$(shell if [ -f "/usr/local/include/odbcinst.h" ]; then echo "cdr_odbc.so"; fi)
|
||||
|
||||
#
|
||||
# FreeTDS stuff...
|
||||
#
|
||||
MODS+=$(shell if [ -f "/usr/include/tds.h" ]; then echo "cdr_tds.so"; fi)
|
||||
MODS+=$(shell if [ -f "/usr/local/include/tds.h" ]; then echo "cdr_tds.so"; fi)
|
||||
|
||||
#
|
||||
# PGSQL stuff... Autoconf anyone??
|
||||
#
|
||||
@@ -55,7 +32,7 @@ CFLAGS+=$(shell if [ -d /usr/include/pgsql ]; then echo "-I/usr/include/pgsql";
|
||||
CFLAGS+=$(shell if [ -d /usr/include/postgresql ]; then echo "-I/usr/include/postgresql"; fi)
|
||||
CFLAGS+=$(shell if [ -d /usr/local/include/pgsql ]; then echo "-I/usr/local/include/pgsql"; fi)
|
||||
CFLAGS+=$(shell if [ -d /opt/pgsql/include ]; then echo "-I/opt/pgsql/include"; fi)
|
||||
#CFLAGS+=$(shell if [ -f /usr/include/libpq-fe.h ]; then echo "-I/usr/include"; fi)
|
||||
CFLAGS+=$(shell if [ -f /usr/include/libpq-fe.h ]; then echo "-I/usr/include"; fi)
|
||||
MLFLAGS=
|
||||
MLFLAGS+=$(shell if [ -d /usr/lib/pgsql ]; then echo "-L/usr/lib/pgsql"; fi)
|
||||
MLFLAGS+=$(shell if [ -d /usr/local/pgsql/lib ]; then echo "-L/usr/local/pgsql/lib"; fi)
|
||||
@@ -63,11 +40,6 @@ MLFLAGS+=$(shell if [ -d /usr/local/lib/pgsql ]; then echo "-L/usr/local/lib/pgs
|
||||
MLFLAGS+=$(shell if [ -d /opt/pgsql/lib ]; then echo "-L/opt/pgsql/lib"; fi)
|
||||
MLFLAGS+=$(shell if [ -f /usr/lib/libpq.so ]; then echo "-L/usr/lib"; fi)
|
||||
|
||||
#
|
||||
# SQLIte stuff...
|
||||
#
|
||||
MODS+=$(shell if [ -f "/usr/include/sqlite.h" ]; then echo "cdr_sqlite.so"; fi)
|
||||
|
||||
all: depend $(MODS)
|
||||
|
||||
install: all
|
||||
@@ -86,15 +58,9 @@ endif
|
||||
cdr_odbc.so: cdr_odbc.o
|
||||
$(CC) $(SOLINK) -o $@ $< -lodbc $(MLFLAGS)
|
||||
|
||||
cdr_tds.so: cdr_tds.o
|
||||
$(CC) $(SOLINK) -o $@ $< -ltds $(MLFLAGS)
|
||||
|
||||
cdr_pgsql.so: cdr_pgsql.o
|
||||
$(CC) $(SOLINK) -o $@ $< -lpq -lz $(MLFLAGS)
|
||||
|
||||
cdr_sqlite.so: cdr_sqlite.o
|
||||
$(CC) $(SOLINK) -o $@ $< -lsqlite $(MLFLAGS)
|
||||
|
||||
depend: .depend
|
||||
|
||||
.depend:
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include <asterisk/cdr.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include "../asterisk.h"
|
||||
#include "../astconf.h"
|
||||
|
||||
@@ -33,7 +32,6 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@@ -72,16 +70,16 @@ static char *name = "csv";
|
||||
|
||||
static FILE *mf = NULL;
|
||||
|
||||
static int append_string(char *buf, char *s, size_t bufsize)
|
||||
static int append_string(char *buf, char *s, int len)
|
||||
{
|
||||
int pos = strlen(buf);
|
||||
int spos = 0;
|
||||
int error = 0;
|
||||
if (pos >= bufsize - 4)
|
||||
if (pos >= len - 4)
|
||||
return -1;
|
||||
buf[pos++] = '\"';
|
||||
error = -1;
|
||||
while(pos < bufsize - 3) {
|
||||
while(pos < len - 3) {
|
||||
if (!s[spos]) {
|
||||
error = 0;
|
||||
break;
|
||||
@@ -97,87 +95,87 @@ static int append_string(char *buf, char *s, size_t bufsize)
|
||||
return error;
|
||||
}
|
||||
|
||||
static int append_int(char *buf, int s, size_t bufsize)
|
||||
static int append_int(char *buf, int s, int len)
|
||||
{
|
||||
char tmp[32];
|
||||
int pos = strlen(buf);
|
||||
snprintf(tmp, sizeof(tmp), "%d", s);
|
||||
if (pos + strlen(tmp) > bufsize - 3)
|
||||
if (pos + strlen(tmp) > len - 3)
|
||||
return -1;
|
||||
strncat(buf, tmp, bufsize - strlen(buf) - 1);
|
||||
strncat(buf, tmp, len);
|
||||
pos = strlen(buf);
|
||||
buf[pos++] = ',';
|
||||
buf[pos++] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int append_date(char *buf, struct timeval tv, size_t bufsize)
|
||||
static int append_date(char *buf, struct timeval tv, int len)
|
||||
{
|
||||
char tmp[80] = "";
|
||||
char tmp[80];
|
||||
struct tm tm;
|
||||
time_t t;
|
||||
t = tv.tv_sec;
|
||||
if (strlen(buf) > bufsize - 3)
|
||||
if (strlen(buf) > len - 3)
|
||||
return -1;
|
||||
if (!tv.tv_sec && !tv.tv_usec) {
|
||||
strncat(buf, ",", bufsize - strlen(buf) - 1);
|
||||
strncat(buf, ",", len);
|
||||
return 0;
|
||||
}
|
||||
localtime_r(&t,&tm);
|
||||
strftime(tmp, sizeof(tmp), DATE_FORMAT, &tm);
|
||||
return append_string(buf, tmp, bufsize);
|
||||
return append_string(buf, tmp, len);
|
||||
}
|
||||
|
||||
static int build_csv_record(char *buf, size_t bufsize, struct ast_cdr *cdr)
|
||||
static int build_csv_record(char *buf, int len, struct ast_cdr *cdr)
|
||||
{
|
||||
|
||||
buf[0] = '\0';
|
||||
/* Account code */
|
||||
append_string(buf, cdr->accountcode, bufsize);
|
||||
append_string(buf, cdr->accountcode, len);
|
||||
/* Source */
|
||||
append_string(buf, cdr->src, bufsize);
|
||||
append_string(buf, cdr->src, len);
|
||||
/* Destination */
|
||||
append_string(buf, cdr->dst, bufsize);
|
||||
append_string(buf, cdr->dst, len);
|
||||
/* Destination context */
|
||||
append_string(buf, cdr->dcontext, bufsize);
|
||||
append_string(buf, cdr->dcontext, len);
|
||||
/* Caller*ID */
|
||||
append_string(buf, cdr->clid, bufsize);
|
||||
append_string(buf, cdr->clid, len);
|
||||
/* Channel */
|
||||
append_string(buf, cdr->channel, bufsize);
|
||||
append_string(buf, cdr->channel, len);
|
||||
/* Destination Channel */
|
||||
append_string(buf, cdr->dstchannel, bufsize);
|
||||
append_string(buf, cdr->dstchannel, len);
|
||||
/* Last Application */
|
||||
append_string(buf, cdr->lastapp, bufsize);
|
||||
append_string(buf, cdr->lastapp, len);
|
||||
/* Last Data */
|
||||
append_string(buf, cdr->lastdata, bufsize);
|
||||
append_string(buf, cdr->lastdata, len);
|
||||
/* Start Time */
|
||||
append_date(buf, cdr->start, bufsize);
|
||||
append_date(buf, cdr->start, len);
|
||||
/* Answer Time */
|
||||
append_date(buf, cdr->answer, bufsize);
|
||||
append_date(buf, cdr->answer, len);
|
||||
/* End Time */
|
||||
append_date(buf, cdr->end, bufsize);
|
||||
append_date(buf, cdr->end, len);
|
||||
/* Duration */
|
||||
append_int(buf, cdr->duration, bufsize);
|
||||
append_int(buf, cdr->duration, len);
|
||||
/* Billable seconds */
|
||||
append_int(buf, cdr->billsec, bufsize);
|
||||
append_int(buf, cdr->billsec, len);
|
||||
/* Disposition */
|
||||
append_string(buf, ast_cdr_disp2str(cdr->disposition), bufsize);
|
||||
append_string(buf, ast_cdr_disp2str(cdr->disposition), len);
|
||||
/* AMA Flags */
|
||||
append_string(buf, ast_cdr_flags2str(cdr->amaflags), bufsize);
|
||||
append_string(buf, ast_cdr_flags2str(cdr->amaflags), len);
|
||||
|
||||
#ifdef CSV_LOGUNIQUEID
|
||||
/* Unique ID */
|
||||
append_string(buf, cdr->uniqueid, bufsize);
|
||||
append_string(buf, cdr->uniqueid, len);
|
||||
#endif
|
||||
#ifdef CSV_LOGUSERFIELD
|
||||
/* append the user field */
|
||||
append_string(buf, cdr->userfield,bufsize);
|
||||
append_string(buf, cdr->userfield,len);
|
||||
#endif
|
||||
/* If we hit the end of our buffer, log an error */
|
||||
if (strlen(buf) < bufsize - 5) {
|
||||
if (strlen(buf) < len - 5) {
|
||||
/* Trim off trailing comma */
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
strncat(buf, "\n", bufsize - strlen(buf) - 1);
|
||||
strncat(buf, "\n", len);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
@@ -185,7 +183,7 @@ static int build_csv_record(char *buf, size_t bufsize, struct ast_cdr *cdr)
|
||||
|
||||
static int writefile(char *s, char *acc)
|
||||
{
|
||||
char tmp[AST_CONFIG_MAX_PATH];
|
||||
char tmp[256];
|
||||
FILE *f;
|
||||
if (strchr(acc, '/') || (acc[0] == '.')) {
|
||||
ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n", acc);
|
||||
@@ -196,7 +194,6 @@ static int writefile(char *s, char *acc)
|
||||
if (!f)
|
||||
return -1;
|
||||
fputs(s, f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
@@ -207,19 +204,19 @@ static int csv_log(struct ast_cdr *cdr)
|
||||
/* Make sure we have a big enough buf */
|
||||
char buf[1024];
|
||||
char csvmaster[AST_CONFIG_MAX_PATH];
|
||||
snprintf(csvmaster, sizeof(csvmaster),"%s/%s/%s", ast_config_AST_LOG_DIR, CSV_LOG_DIR, CSV_MASTER);
|
||||
snprintf((char *)csvmaster,sizeof(csvmaster)-1,"%s/%s/%s",(char *)ast_config_AST_LOG_DIR,CSV_LOG_DIR,CSV_MASTER);
|
||||
#if 0
|
||||
printf("[CDR] %s ('%s' -> '%s') Dur: %ds Bill: %ds Disp: %s Flags: %s Account: [%s]\n", cdr->channel, cdr->src, cdr->dst, cdr->duration, cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), cdr->accountcode);
|
||||
#endif
|
||||
if (build_csv_record(buf, sizeof(buf), cdr)) {
|
||||
ast_log(LOG_WARNING, "Unable to create CSV record in %d bytes. CDR not recorded!\n", (int)sizeof(buf));
|
||||
ast_log(LOG_WARNING, "Unable to create CSV record in %d bytes. CDR not recorded!\n", sizeof(buf));
|
||||
} else {
|
||||
/* because of the absolutely unconditional need for the
|
||||
highest reliability possible in writing billing records,
|
||||
we open write and close the log file each time */
|
||||
mf = fopen(csvmaster, "a");
|
||||
if (!mf) {
|
||||
ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", csvmaster, strerror(errno));
|
||||
ast_log(LOG_ERROR, "Unable to re-open master file %s\n", csvmaster);
|
||||
}
|
||||
if (mf) {
|
||||
fputs(buf, mf);
|
||||
@@ -227,9 +224,9 @@ static int csv_log(struct ast_cdr *cdr)
|
||||
fclose(mf);
|
||||
mf = NULL;
|
||||
}
|
||||
if (!ast_strlen_zero(cdr->accountcode)) {
|
||||
if (strlen(cdr->accountcode)) {
|
||||
if (writefile(buf, cdr->accountcode))
|
||||
ast_log(LOG_WARNING, "Unable to write CSV record to account file '%s' : %s\n", cdr->accountcode, strerror(errno));
|
||||
ast_log(LOG_WARNING, "Unable to write CSV record to account file '%s'\n", cdr->accountcode);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Asterisk Call Manager CDR records.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/cdr.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/manager.h>
|
||||
#include <asterisk/config.h>
|
||||
#include "../asterisk.h"
|
||||
#include "../astconf.h"
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#define DATE_FORMAT "%Y-%m-%d %T"
|
||||
#define CONF_FILE "cdr_manager.conf"
|
||||
|
||||
static char *desc = "Asterisk Call Manager CDR Backend";
|
||||
static char *name = "cdr_as";
|
||||
|
||||
static int enablecdr = 0;
|
||||
|
||||
static void loadconfigurationfile(void)
|
||||
{
|
||||
char *cat;
|
||||
struct ast_config *cfg;
|
||||
struct ast_variable *v;
|
||||
|
||||
cfg = ast_load(CONF_FILE);
|
||||
if (!cfg) {
|
||||
/* Standard configuration */
|
||||
enablecdr = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
cat = ast_category_browse(cfg, NULL);
|
||||
while (cat) {
|
||||
if (!strcasecmp(cat, "general")) {
|
||||
v = ast_variable_browse(cfg, cat);
|
||||
while (v) {
|
||||
if (!strcasecmp(v->name, "enabled")) {
|
||||
enablecdr = ast_true(v->value);
|
||||
}
|
||||
|
||||
v = v->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Next category */
|
||||
cat = ast_category_browse(cfg, cat);
|
||||
}
|
||||
|
||||
ast_destroy(cfg);
|
||||
}
|
||||
|
||||
static int manager_log(struct ast_cdr *cdr)
|
||||
{
|
||||
time_t t;
|
||||
struct tm timeresult;
|
||||
char strStartTime[80] = "";
|
||||
char strAnswerTime[80] = "";
|
||||
char strEndTime[80] = "";
|
||||
|
||||
if (!enablecdr)
|
||||
return 0;
|
||||
|
||||
t = cdr->start.tv_sec;
|
||||
localtime_r(&t, &timeresult);
|
||||
strftime(strStartTime, sizeof(strStartTime), DATE_FORMAT, &timeresult);
|
||||
|
||||
if (cdr->answer.tv_sec) {
|
||||
t = cdr->answer.tv_sec;
|
||||
localtime_r(&t, &timeresult);
|
||||
strftime(strAnswerTime, sizeof(strAnswerTime), DATE_FORMAT, &timeresult);
|
||||
}
|
||||
|
||||
t = cdr->end.tv_sec;
|
||||
localtime_r(&t, &timeresult);
|
||||
strftime(strEndTime, sizeof(strEndTime), DATE_FORMAT, &timeresult);
|
||||
|
||||
manager_event(EVENT_FLAG_CALL, "Cdr",
|
||||
"AccountCode: %s\r\n"
|
||||
"Source: %s\r\n"
|
||||
"Destination: %s\r\n"
|
||||
"DestinationContext: %s\r\n"
|
||||
"CallerID: %s\r\n"
|
||||
"Channel: %s\r\n"
|
||||
"DestinationChannel: %s\r\n"
|
||||
"LastApplication: %s\r\n"
|
||||
"LastData: %s\r\n"
|
||||
"StartTime: %s\r\n"
|
||||
"AnswerTime: %s\r\n"
|
||||
"EndTime: %s\r\n"
|
||||
"Duration: %d\r\n"
|
||||
"BillableSeconds: %d\r\n"
|
||||
"Disposition: %s\r\n"
|
||||
"AMAFlags: %s\r\n"
|
||||
"UniqueID: %s\r\n"
|
||||
"UserField: %s\r\n",
|
||||
cdr->accountcode, cdr->src, cdr->dst, cdr->dcontext, cdr->clid, cdr->channel,
|
||||
cdr->dstchannel, cdr->lastapp, cdr->lastdata, strStartTime, strAnswerTime, strEndTime,
|
||||
cdr->duration, cdr->billsec, ast_cdr_disp2str(cdr->disposition),
|
||||
ast_cdr_flags2str(cdr->amaflags), cdr->uniqueid, cdr->userfield);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return desc;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
ast_cdr_unregister(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
/* Configuration file */
|
||||
loadconfigurationfile();
|
||||
|
||||
res = ast_cdr_register(name, desc, manager_log);
|
||||
if (res) {
|
||||
ast_log(LOG_ERROR, "Unable to register Asterisk Call Manager CDR handling\n");
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int reload(void)
|
||||
{
|
||||
loadconfigurationfile();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
318
cdr/cdr_odbc.c
318
cdr/cdr_odbc.c
@@ -3,12 +3,13 @@
|
||||
*
|
||||
* ODBC CDR Backend
|
||||
*
|
||||
* Copyright (C) 2003-2005, Digium, Inc.
|
||||
*
|
||||
* Brian K. West <brian@bkw.org>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
* the GNU General Public License.
|
||||
*
|
||||
* Copyright (c) 2003 Digium, Inc.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -36,12 +37,11 @@
|
||||
static char *desc = "ODBC CDR Backend";
|
||||
static char *name = "ODBC";
|
||||
static char *config = "cdr_odbc.conf";
|
||||
static char *dsn = NULL, *username = NULL, *password = NULL;
|
||||
static int dsn_alloc = 0, username_alloc = 0, password_alloc = 0;
|
||||
static int loguniqueid = 0;
|
||||
static char *dsn = NULL, *username = NULL, *password = NULL, *loguniqueid = NULL;
|
||||
static int dsn_alloc = 0, username_alloc = 0, password_alloc = 0, loguniqueid_alloc = 0;
|
||||
static int connected = 0;
|
||||
|
||||
AST_MUTEX_DEFINE_STATIC(odbc_lock);
|
||||
static ast_mutex_t odbc_lock = AST_MUTEX_INITIALIZER;
|
||||
|
||||
static int odbc_do_query(void);
|
||||
static int odbc_init(void);
|
||||
@@ -56,40 +56,51 @@ static int odbc_log(struct ast_cdr *cdr)
|
||||
short int ODBC_mlen;
|
||||
int ODBC_res;
|
||||
char ODBC_msg[200], ODBC_stat[10];
|
||||
char sqlcmd[2048] = "", timestr[128];
|
||||
char sqlcmd[2048], timestr[128];
|
||||
int res = 0;
|
||||
struct tm tm;
|
||||
struct timeval tv;
|
||||
time_t t;
|
||||
|
||||
localtime_r(&cdr->start.tv_sec,&tm);
|
||||
gettimeofday(&tv,NULL);
|
||||
t = tv.tv_sec;
|
||||
localtime_r(&t,&tm);
|
||||
|
||||
ast_mutex_lock(&odbc_lock);
|
||||
strftime(timestr, sizeof(timestr), DATE_FORMAT, &tm);
|
||||
strftime(timestr,128,DATE_FORMAT,&tm);
|
||||
memset(sqlcmd,0,2048);
|
||||
if (loguniqueid) {
|
||||
snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO cdr "
|
||||
if((loguniqueid != NULL) && ((strcmp(loguniqueid, "1") == 0) || (strcmp(loguniqueid, "yes") == 0)))
|
||||
{
|
||||
sprintf(sqlcmd,"INSERT INTO cdr "
|
||||
"(calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,"
|
||||
"lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid,userfield) "
|
||||
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
|
||||
} else {
|
||||
snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO cdr "
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(sqlcmd,"INSERT INTO cdr "
|
||||
"(calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,"
|
||||
"duration,billsec,disposition,amaflags,accountcode) "
|
||||
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
|
||||
}
|
||||
|
||||
if (!connected) {
|
||||
res = odbc_init();
|
||||
if (res < 0) {
|
||||
if(!connected)
|
||||
{
|
||||
res = odbc_init();
|
||||
if(res < 0)
|
||||
{
|
||||
connected = 0;
|
||||
ast_mutex_unlock(&odbc_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ODBC_res = SQLAllocHandle(SQL_HANDLE_STMT, ODBC_con, &ODBC_stmt);
|
||||
|
||||
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
|
||||
if (option_verbose > 10)
|
||||
if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
|
||||
{
|
||||
if(option_verbose > 3)
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Failure in AllocStatement %d\n", ODBC_res);
|
||||
SQLGetDiagRec(SQL_HANDLE_DBC, ODBC_con, 1, ODBC_stat, &ODBC_err, ODBC_msg, 100, &ODBC_mlen);
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
|
||||
@@ -104,8 +115,9 @@ static int odbc_log(struct ast_cdr *cdr)
|
||||
|
||||
ODBC_res = SQLPrepare(ODBC_stmt, sqlcmd, SQL_NTS);
|
||||
|
||||
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
|
||||
if (option_verbose > 10)
|
||||
if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
|
||||
{
|
||||
if(option_verbose > 3)
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error in PREPARE %d\n", ODBC_res);
|
||||
SQLGetDiagRec(SQL_HANDLE_DBC, ODBC_con, 1, ODBC_stat, &ODBC_err, ODBC_msg, 100, &ODBC_mlen);
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
|
||||
@@ -114,53 +126,61 @@ static int odbc_log(struct ast_cdr *cdr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
SQLBindParameter(ODBC_stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(timestr), 0, ×tr, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->clid), 0, cdr->clid, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->src), 0, cdr->src, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dst), 0, cdr->dst, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dcontext), 0, cdr->dcontext, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->channel), 0, cdr->channel, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dstchannel), 0, cdr->dstchannel, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->lastapp), 0, cdr->lastapp, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->lastdata), 0, cdr->lastdata, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 10, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->duration, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 11, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->billsec, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 12, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->disposition, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 13, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->amaflags, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 14, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->accountcode), 0, cdr->accountcode, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, ×tr, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->clid, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->src, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->dst, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->dcontext, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->channel, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->dstchannel, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->lastapp, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->lastdata, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 10, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &cdr->duration, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 11, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &cdr->billsec, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 12, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &cdr->disposition, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 13, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &cdr->amaflags, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 14, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->accountcode, 0, NULL);
|
||||
|
||||
if (loguniqueid) {
|
||||
SQLBindParameter(ODBC_stmt, 15, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->uniqueid), 0, cdr->uniqueid, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 16, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->userfield), 0, cdr->userfield, 0, NULL);
|
||||
if((loguniqueid != NULL) && ((strcmp(loguniqueid, "1") == 0) || (strcmp(loguniqueid, "yes") == 0)))
|
||||
{
|
||||
SQLBindParameter(ODBC_stmt, 15, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->uniqueid, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 16, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->userfield, 0, NULL);
|
||||
}
|
||||
|
||||
if (connected) {
|
||||
if(connected)
|
||||
{
|
||||
res = odbc_do_query();
|
||||
if (res < 0) {
|
||||
if (option_verbose > 10)
|
||||
if(res < 0)
|
||||
{
|
||||
if(option_verbose > 3)
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query FAILED Call not logged!\n");
|
||||
res = odbc_init();
|
||||
if (option_verbose > 10)
|
||||
if(option_verbose > 3)
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Reconnecting to dsn %s\n", dsn);
|
||||
if (res < 0) {
|
||||
if (option_verbose > 10)
|
||||
if(res < 0)
|
||||
{
|
||||
if(option_verbose > 3)
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: %s has gone away!\n", dsn);
|
||||
connected = 0;
|
||||
} else {
|
||||
if (option_verbose > 10)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(option_verbose > 3)
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Trying Query again!\n");
|
||||
res = odbc_do_query();
|
||||
if (res < 0) {
|
||||
if (option_verbose > 10)
|
||||
if(res < 0)
|
||||
{
|
||||
if(option_verbose > 3)
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query FAILED Call not logged!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (option_verbose > 10)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(option_verbose > 3)
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query FAILED Call not logged!\n");
|
||||
}
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
|
||||
ast_mutex_unlock(&odbc_lock);
|
||||
return 0;
|
||||
}
|
||||
@@ -173,8 +193,9 @@ char *description(void)
|
||||
static int odbc_unload_module(void)
|
||||
{
|
||||
ast_mutex_lock(&odbc_lock);
|
||||
if (connected) {
|
||||
if (option_verbose > 10)
|
||||
if (connected)
|
||||
{
|
||||
if(option_verbose > 3)
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Disconnecting from %s\n", dsn);
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
|
||||
SQLDisconnect(ODBC_con);
|
||||
@@ -182,29 +203,38 @@ static int odbc_unload_module(void)
|
||||
SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
|
||||
connected = 0;
|
||||
}
|
||||
if (dsn && dsn_alloc) {
|
||||
if (option_verbose > 10)
|
||||
if (dsn && dsn_alloc)
|
||||
{
|
||||
if(option_verbose > 3)
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free dsn\n");
|
||||
free(dsn);
|
||||
dsn = NULL;
|
||||
dsn_alloc = 0;
|
||||
}
|
||||
if (username && username_alloc) {
|
||||
if (option_verbose > 10)
|
||||
if (username && username_alloc)
|
||||
{
|
||||
if(option_verbose > 3)
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free username\n");
|
||||
free(username);
|
||||
username = NULL;
|
||||
username_alloc = 0;
|
||||
}
|
||||
if (password && password_alloc) {
|
||||
if (option_verbose > 10)
|
||||
if (password && password_alloc)
|
||||
{
|
||||
if(option_verbose > 3)
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free password\n");
|
||||
free(password);
|
||||
password = NULL;
|
||||
password_alloc = 0;
|
||||
}
|
||||
loguniqueid = 0;
|
||||
|
||||
if (loguniqueid && loguniqueid_alloc)
|
||||
{
|
||||
if(option_verbose > 3)
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free loguniqueid\n");
|
||||
free(loguniqueid);
|
||||
loguniqueid = NULL;
|
||||
loguniqueid_alloc = 0;
|
||||
}
|
||||
ast_cdr_unregister(name);
|
||||
ast_mutex_unlock(&odbc_lock);
|
||||
return 0;
|
||||
@@ -220,7 +250,8 @@ static int odbc_load_module(void)
|
||||
ast_mutex_lock(&odbc_lock);
|
||||
|
||||
cfg = ast_load(config);
|
||||
if (!cfg) {
|
||||
if (!cfg)
|
||||
{
|
||||
ast_log(LOG_WARNING, "cdr_odbc: Unable to load config for ODBC CDR's: %s\n", config);
|
||||
goto out;
|
||||
}
|
||||
@@ -232,85 +263,110 @@ static int odbc_load_module(void)
|
||||
}
|
||||
|
||||
tmp = ast_variable_retrieve(cfg,"global","dsn");
|
||||
if (tmp) {
|
||||
if (tmp)
|
||||
{
|
||||
dsn = malloc(strlen(tmp) + 1);
|
||||
if (dsn != NULL) {
|
||||
memset(dsn, 0, strlen(tmp) + 1);
|
||||
if (dsn != NULL)
|
||||
{
|
||||
dsn_alloc = 1;
|
||||
strncpy(dsn, tmp, strlen(tmp));
|
||||
} else {
|
||||
ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n");
|
||||
res = -1;
|
||||
goto out;
|
||||
strcpy(dsn,tmp);
|
||||
}
|
||||
} else {
|
||||
else
|
||||
{
|
||||
ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ast_log(LOG_WARNING,"cdr_odbc: dsn not specified. Assuming asteriskdb\n");
|
||||
dsn = "asteriskdb";
|
||||
}
|
||||
|
||||
tmp = ast_variable_retrieve(cfg,"global","username");
|
||||
if (tmp) {
|
||||
if (tmp)
|
||||
{
|
||||
username = malloc(strlen(tmp) + 1);
|
||||
if (username != NULL) {
|
||||
memset(username, 0, strlen(tmp) + 1);
|
||||
if (username != NULL)
|
||||
{
|
||||
username_alloc = 1;
|
||||
strncpy(username, tmp, strlen(tmp));
|
||||
} else {
|
||||
ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n");
|
||||
res = -1;
|
||||
goto out;
|
||||
strcpy(username,tmp);
|
||||
}
|
||||
} else {
|
||||
else
|
||||
{
|
||||
ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ast_log(LOG_WARNING,"cdr_odbc: username not specified. Assuming root\n");
|
||||
username = "root";
|
||||
}
|
||||
|
||||
tmp = ast_variable_retrieve(cfg,"global","password");
|
||||
if (tmp) {
|
||||
if (tmp)
|
||||
{
|
||||
password = malloc(strlen(tmp) + 1);
|
||||
if (password != NULL) {
|
||||
memset(password, 0, strlen(tmp) + 1);
|
||||
if (password != NULL)
|
||||
{
|
||||
password_alloc = 1;
|
||||
strncpy(password, tmp, strlen(tmp));
|
||||
} else {
|
||||
ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n");
|
||||
res = -1;
|
||||
goto out;
|
||||
strcpy(password,tmp);
|
||||
}
|
||||
} else {
|
||||
else
|
||||
{
|
||||
ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ast_log(LOG_WARNING,"cdr_odbc: database password not specified. Assuming blank\n");
|
||||
password = "";
|
||||
}
|
||||
|
||||
tmp = ast_variable_retrieve(cfg,"global","loguniqueid");
|
||||
if (tmp) {
|
||||
loguniqueid = ast_true(tmp);
|
||||
if (loguniqueid) {
|
||||
if (tmp)
|
||||
{
|
||||
loguniqueid = malloc(strlen(tmp) + 1);
|
||||
if (loguniqueid != NULL)
|
||||
{
|
||||
strcpy(loguniqueid,tmp);
|
||||
loguniqueid_alloc = 1;
|
||||
ast_log(LOG_NOTICE,"cdr_odbc: Logging uniqueid\n");
|
||||
} else {
|
||||
ast_log(LOG_ERROR,"cdr_odbc: Not logging uniqueid\n");
|
||||
}
|
||||
} else {
|
||||
else
|
||||
{
|
||||
ast_log(LOG_ERROR,"cdr_odbc: Not logging uniqueid\n");
|
||||
loguniqueid_alloc = 1;
|
||||
loguniqueid = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ast_log(LOG_WARNING,"cdr_odbc: Not logging uniqueid\n");
|
||||
loguniqueid = 0;
|
||||
loguniqueid = NULL;
|
||||
}
|
||||
|
||||
ast_destroy(cfg);
|
||||
if (option_verbose > 2) {
|
||||
ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: dsn is %s\n",dsn);
|
||||
ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: username is %s\n",username);
|
||||
ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: password is [secret]\n");
|
||||
if(option_verbose > 3)
|
||||
{
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: dsn is %s\n",dsn);
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: username is %s\n",username);
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: password is [secret]\n");
|
||||
|
||||
}
|
||||
|
||||
res = odbc_init();
|
||||
if (res < 0) {
|
||||
if(res < 0)
|
||||
{
|
||||
ast_log(LOG_ERROR, "cdr_odbc: Unable to connect to datasource: %s\n", dsn);
|
||||
if (option_verbose > 2) {
|
||||
ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: Unable to connect to datasource: %s\n", dsn);
|
||||
}
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Unable to connect to datasource: %s\n", dsn);
|
||||
}
|
||||
|
||||
res = ast_cdr_register(name, desc, odbc_log);
|
||||
if (res) {
|
||||
if (res)
|
||||
{
|
||||
ast_log(LOG_ERROR, "cdr_odbc: Unable to register ODBC CDR handling\n");
|
||||
}
|
||||
out:
|
||||
@@ -320,22 +376,25 @@ out:
|
||||
|
||||
static int odbc_do_query(void)
|
||||
{
|
||||
long int ODBC_err;
|
||||
long int ODBC_err;
|
||||
int ODBC_res;
|
||||
short int ODBC_mlen;
|
||||
char ODBC_msg[200], ODBC_stat[10];
|
||||
|
||||
short int ODBC_mlen;
|
||||
char ODBC_msg[200], ODBC_stat[10];
|
||||
|
||||
ODBC_res = SQLExecute(ODBC_stmt);
|
||||
|
||||
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
|
||||
if (option_verbose > 10)
|
||||
|
||||
if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
|
||||
{
|
||||
if(option_verbose > 3)
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error in Query %d\n", ODBC_res);
|
||||
SQLGetDiagRec(SQL_HANDLE_DBC, ODBC_con, 1, ODBC_stat, &ODBC_err, ODBC_msg, 100, &ODBC_mlen);
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
|
||||
connected = 0;
|
||||
return -1;
|
||||
} else {
|
||||
if (option_verbose > 10)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(option_verbose > 3)
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query Successful!\n");
|
||||
connected = 1;
|
||||
}
|
||||
@@ -349,10 +408,13 @@ static int odbc_init(void)
|
||||
int ODBC_res;
|
||||
char ODBC_msg[200], ODBC_stat[10];
|
||||
|
||||
if (ODBC_env == SQL_NULL_HANDLE || connected == 0) {
|
||||
if ( ODBC_env == SQL_NULL_HANDLE || connected == 0 )
|
||||
{
|
||||
ODBC_res = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &ODBC_env);
|
||||
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
|
||||
if (option_verbose > 10)
|
||||
|
||||
if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
|
||||
{
|
||||
if(option_verbose > 3)
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error AllocHandle\n");
|
||||
connected = 0;
|
||||
return -1;
|
||||
@@ -360,8 +422,9 @@ static int odbc_init(void)
|
||||
|
||||
ODBC_res = SQLSetEnvAttr(ODBC_env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
|
||||
|
||||
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
|
||||
if (option_verbose > 10)
|
||||
if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
|
||||
{
|
||||
if(option_verbose > 3)
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error SetEnv\n");
|
||||
SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
|
||||
connected = 0;
|
||||
@@ -370,27 +433,32 @@ static int odbc_init(void)
|
||||
|
||||
ODBC_res = SQLAllocHandle(SQL_HANDLE_DBC, ODBC_env, &ODBC_con);
|
||||
|
||||
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
|
||||
if (option_verbose > 10)
|
||||
if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
|
||||
{
|
||||
if(option_verbose > 3)
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error AllocHDB %d\n", ODBC_res);
|
||||
SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
|
||||
connected = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
SQLSetConnectAttr(ODBC_con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)10, 0);
|
||||
}
|
||||
|
||||
ODBC_res = SQLConnect(ODBC_con, (SQLCHAR*)dsn, SQL_NTS, (SQLCHAR*)username, SQL_NTS, (SQLCHAR*)password, SQL_NTS);
|
||||
|
||||
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
|
||||
if (option_verbose > 10)
|
||||
if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
|
||||
{
|
||||
if(option_verbose > 3)
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error SQLConnect %d\n", ODBC_res);
|
||||
SQLGetDiagRec(SQL_HANDLE_DBC, ODBC_con, 1, ODBC_stat, &ODBC_err, ODBC_msg, 100, &ODBC_mlen);
|
||||
SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
|
||||
connected = 0;
|
||||
return -1;
|
||||
} else {
|
||||
if (option_verbose > 10)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(option_verbose > 3)
|
||||
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Connected to %s\n", dsn);
|
||||
connected = 1;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ static char *pghostname = NULL, *pgdbname = NULL, *pgdbuser = NULL, *pgpassword
|
||||
static int hostname_alloc = 0, dbname_alloc = 0, dbuser_alloc = 0, password_alloc = 0, dbsock_alloc = 0, dbport_alloc = 0;
|
||||
static int connected = 0;
|
||||
|
||||
AST_MUTEX_DEFINE_STATIC(pgsql_lock);
|
||||
static ast_mutex_t pgsql_lock = AST_MUTEX_INITIALIZER;
|
||||
|
||||
PGconn *conn;
|
||||
PGresult *result;
|
||||
@@ -49,13 +49,19 @@ PGresult *result;
|
||||
static int pgsql_log(struct ast_cdr *cdr)
|
||||
{
|
||||
struct tm tm;
|
||||
char sqlcmd[2048] = "", timestr[128];
|
||||
char *pgerror;
|
||||
struct timeval tv;
|
||||
char sqlcmd[2048], timestr[128];
|
||||
time_t t;
|
||||
char *pgerror;
|
||||
|
||||
ast_mutex_lock(&pgsql_lock);
|
||||
|
||||
localtime_r(&cdr->start.tv_sec,&tm);
|
||||
strftime(timestr, sizeof(timestr), DATE_FORMAT, &tm);
|
||||
memset(sqlcmd,0,2048);
|
||||
|
||||
gettimeofday(&tv,NULL);
|
||||
t = tv.tv_sec;
|
||||
localtime_r(&t,&tm);
|
||||
strftime(timestr,128,DATE_FORMAT,&tm);
|
||||
|
||||
if ((!connected) && pghostname && pgdbuser && pgpassword && pgdbname) {
|
||||
conn = PQsetdbLogin(pghostname, pgdbport, NULL, NULL, pgdbname, pgdbuser, pgpassword);
|
||||
@@ -99,7 +105,7 @@ static int pgsql_log(struct ast_cdr *cdr)
|
||||
|
||||
ast_log(LOG_DEBUG,"cdr_pgsql: inserting a CDR record.\n");
|
||||
|
||||
snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO cdr (calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid,userfield) VALUES ('%s','%s','%s','%s','%s', '%s','%s','%s','%s',%i,%i,'%s',%i,'%s','%s','%s')",timestr,clid,cdr->src, cdr->dst, dcontext,channel, dstchannel, lastapp, lastdata,cdr->duration,cdr->billsec,ast_cdr_disp2str(cdr->disposition),cdr->amaflags, cdr->accountcode, uniqueid, userfield);
|
||||
sprintf(sqlcmd,"INSERT INTO cdr (calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid,userfield) VALUES ('%s','%s','%s','%s','%s', '%s','%s','%s','%s',%i,%i,'%s',%i,'%s','%s','%s')",timestr,clid,cdr->src, cdr->dst, dcontext,channel, dstchannel, lastapp, lastdata,cdr->duration,cdr->billsec,ast_cdr_disp2str(cdr->disposition),cdr->amaflags, cdr->accountcode, uniqueid, userfield);
|
||||
ast_log(LOG_DEBUG,"cdr_pgsql: SQL command executed: %s\n",sqlcmd);
|
||||
|
||||
/* Test to be sure we're still connected... */
|
||||
@@ -118,7 +124,6 @@ static int pgsql_log(struct ast_cdr *cdr)
|
||||
ast_log(LOG_ERROR, "cdr_pgsql: Unable to reconnect to database server %s. Calls will not be logged!\n", pghostname);
|
||||
ast_log(LOG_ERROR, "cdr_pgsql: Reason: %s\n", pgerror);
|
||||
connected = 0;
|
||||
ast_mutex_unlock(&pgsql_lock);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -127,19 +132,6 @@ static int pgsql_log(struct ast_cdr *cdr)
|
||||
pgerror = PQresultErrorMessage(result);
|
||||
ast_log(LOG_ERROR,"cdr_pgsql: Failed to insert call detail record into database!\n");
|
||||
ast_log(LOG_ERROR,"cdr_pgsql: Reason: %s\n", pgerror);
|
||||
ast_log(LOG_ERROR,"cdr_pgsql: Connection may have been lost... attempting to reconnect.\n");
|
||||
PQreset(conn);
|
||||
if (PQstatus(conn) == CONNECTION_OK) {
|
||||
ast_log(LOG_ERROR, "cdr_pgsql: Connection reestablished.\n");
|
||||
connected = 1;
|
||||
result = PQexec(conn, sqlcmd);
|
||||
if ( PQresultStatus(result) != PGRES_COMMAND_OK)
|
||||
{
|
||||
pgerror = PQresultErrorMessage(result);
|
||||
ast_log(LOG_ERROR,"cdr_pgsql: HARD ERROR! Attempted reconnection failed. DROPPING CALL RECORD!\n");
|
||||
ast_log(LOG_ERROR,"cdr_pgsql: Reason: %s\n", pgerror);
|
||||
}
|
||||
}
|
||||
ast_mutex_unlock(&pgsql_lock);
|
||||
return -1;
|
||||
}
|
||||
@@ -155,9 +147,7 @@ char *description(void)
|
||||
|
||||
static int my_unload_module(void)
|
||||
{
|
||||
if (conn)
|
||||
PQfinish(conn);
|
||||
conn = NULL;
|
||||
PQfinish(conn);
|
||||
connected = 0;
|
||||
if (pghostname && hostname_alloc) {
|
||||
free(pghostname);
|
||||
@@ -193,13 +183,20 @@ static int my_unload_module(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_my_load_module(struct ast_config *cfg)
|
||||
static int my_load_module(void)
|
||||
{
|
||||
int res;
|
||||
struct ast_config *cfg;
|
||||
struct ast_variable *var;
|
||||
char *pgerror;
|
||||
char *tmp;
|
||||
|
||||
cfg = ast_load(config);
|
||||
if (!cfg) {
|
||||
ast_log(LOG_WARNING, "Unable to load config for PostgreSQL CDR's: %s\n", config);
|
||||
return 0;
|
||||
}
|
||||
|
||||
var = ast_variable_browse(cfg, "global");
|
||||
if (!var) {
|
||||
/* nothing configured */
|
||||
@@ -210,9 +207,8 @@ static int process_my_load_module(struct ast_config *cfg)
|
||||
if (tmp) {
|
||||
pghostname = malloc(strlen(tmp) + 1);
|
||||
if (pghostname != NULL) {
|
||||
memset(pghostname, 0, strlen(tmp) + 1);
|
||||
hostname_alloc = 1;
|
||||
strncpy(pghostname, tmp, strlen(tmp));
|
||||
strcpy(pghostname,tmp);
|
||||
} else {
|
||||
ast_log(LOG_ERROR,"Out of memory error.\n");
|
||||
return -1;
|
||||
@@ -226,9 +222,8 @@ static int process_my_load_module(struct ast_config *cfg)
|
||||
if (tmp) {
|
||||
pgdbname = malloc(strlen(tmp) + 1);
|
||||
if (pgdbname != NULL) {
|
||||
memset(pgdbname, 0, strlen(tmp) + 1);
|
||||
dbname_alloc = 1;
|
||||
strncpy(pgdbname, tmp, strlen(tmp));
|
||||
strcpy(pgdbname,tmp);
|
||||
} else {
|
||||
ast_log(LOG_ERROR,"Out of memory error.\n");
|
||||
return -1;
|
||||
@@ -242,9 +237,8 @@ static int process_my_load_module(struct ast_config *cfg)
|
||||
if (tmp) {
|
||||
pgdbuser = malloc(strlen(tmp) + 1);
|
||||
if (pgdbuser != NULL) {
|
||||
memset(pgdbuser, 0, strlen(tmp) + 1);
|
||||
dbuser_alloc = 1;
|
||||
strncpy(pgdbuser, tmp, strlen(tmp));
|
||||
strcpy(pgdbuser,tmp);
|
||||
} else {
|
||||
ast_log(LOG_ERROR,"Out of memory error.\n");
|
||||
return -1;
|
||||
@@ -258,9 +252,8 @@ static int process_my_load_module(struct ast_config *cfg)
|
||||
if (tmp) {
|
||||
pgpassword = malloc(strlen(tmp) + 1);
|
||||
if (pgpassword != NULL) {
|
||||
memset(pgpassword, 0, strlen(tmp) + 1);
|
||||
password_alloc = 1;
|
||||
strncpy(pgpassword, tmp, strlen(tmp));
|
||||
strcpy(pgpassword,tmp);
|
||||
} else {
|
||||
ast_log(LOG_ERROR,"Out of memory error.\n");
|
||||
return -1;
|
||||
@@ -274,9 +267,8 @@ static int process_my_load_module(struct ast_config *cfg)
|
||||
if (tmp) {
|
||||
pgdbport = malloc(strlen(tmp) + 1);
|
||||
if (pgdbport != NULL) {
|
||||
memset(pgdbport, 0, strlen(tmp) + 1);
|
||||
dbport_alloc = 1;
|
||||
strncpy(pgdbport, tmp, strlen(tmp));
|
||||
strcpy(pgdbport,tmp);
|
||||
} else {
|
||||
ast_log(LOG_ERROR,"Out of memory error.\n");
|
||||
return -1;
|
||||
@@ -286,6 +278,8 @@ static int process_my_load_module(struct ast_config *cfg)
|
||||
pgdbport = "5432";
|
||||
}
|
||||
|
||||
ast_destroy(cfg);
|
||||
|
||||
ast_log(LOG_DEBUG,"cdr_pgsql: got hostname of %s\n",pghostname);
|
||||
ast_log(LOG_DEBUG,"cdr_pgsql: got port of %s\n",pgdbport);
|
||||
if (pgdbsock)
|
||||
@@ -300,7 +294,7 @@ static int process_my_load_module(struct ast_config *cfg)
|
||||
connected = 1;
|
||||
} else {
|
||||
pgerror = PQerrorMessage(conn);
|
||||
ast_log(LOG_ERROR, "cdr_pgsql: Unable to connect to database server %s. CALLS WILL NOT BE LOGGED!!\n", pghostname);
|
||||
ast_log(LOG_ERROR, "cdr_pgsql: Unable to connect to database server %s. Calls will not be logged!\n", pghostname);
|
||||
ast_log(LOG_ERROR, "cdr_pgsql: Reason: %s\n", pgerror);
|
||||
connected = 0;
|
||||
}
|
||||
@@ -312,20 +306,6 @@ static int process_my_load_module(struct ast_config *cfg)
|
||||
return res;
|
||||
}
|
||||
|
||||
static int my_load_module(void)
|
||||
{
|
||||
struct ast_config *cfg;
|
||||
int res;
|
||||
cfg = ast_load(config);
|
||||
if (!cfg) {
|
||||
ast_log(LOG_WARNING, "Unable to load config for PostgreSQL CDR's: %s\n", config);
|
||||
return 0;
|
||||
}
|
||||
res = process_my_load_module(cfg);
|
||||
ast_destroy(cfg);
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return my_load_module();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user