Compare commits

..

3 Commits
0.7.1 ... 0.1.9

Author SHA1 Message Date
Kevin P. Fleming
435a47f8ed remove extraneous svn:executable properties
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/0.1.9@7221 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-29 18:24:39 +00:00
Kevin P. Fleming
af3d087c1a automatic tag renames
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/0.1.9@7201 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-27 17:18:34 +00:00
Admin Commit
0be2a468a0 This commit was manufactured by cvs2svn to create tag 'v0-1-9'.
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/v0-1-9@371 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2001-10-15 17:39:25 +00:00
747 changed files with 23802 additions and 148231 deletions

54
BUGS
View File

@@ -1,18 +1,44 @@
Asterisk Bug Tracking Information
=================================
* EVERYTHING MARKED WITH "XXX" IN THE SOURCE REPRESENTS A BUG! Sometimes
these bugs are in asterisk, and sometimes they relate to the products
that asterisk uses.
To learn about and report Asterisk bugs or make feature
requests, please visit the official Asterisk Bug Tracker
at:
* In general Asterisk is a very new program, and there are liable to be
many bugs yet to be discovered, so if you think you've found one, please
be sure to report it.
http://bugs.digium.com
* When you flip to call waiting on a tormenta channel while you have a
three way call up, the parties in the three way cannot hear one another
in the general case.
For more information on using the bug tracker, or to
learn how you can contribute by acting as a bug marshal
please see:
======================================================================
Short report on the voicemail system
======================================================================
Stuff We Need:
http://www.digium.com/bugtracker.html
Thank you!
Mark
-Date/Time (conversion on the fly for different locales)
-A more fleshed/emphasized Main Menu
-Mailbox Options
-useful for allowing user to set certain options
-Notification of new vs. old messages
-Notification of first and last messages (old and new)
and a return to the Main Menu @ the end
**-Better handling of lack of user input, specifically...
infinite loops...
currently found in: vm-instructions
vm-msginstruct
System MUST disconnect user for inactivity
-Mid message menu w/
pause/unpause
seeking
callback option
option to get caller's number if available
option to leave message directly on caller's voicemail
if he/she has account on system
-Also redesign the End Of Message Menu
-Efficienty Question...
Better to always rename msgs to being @ 0001
or...
Better to append new msgs numerically @ the
end and use software to traverse them in
order...saving cpu cycles on renaming files
..could get messy w/ lots of users

209
CHANGES
View File

@@ -1,212 +1,3 @@
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
Asterisk 0.7.0
-- Removed MP3 format and codec
-- Can now load and unload SIP,IAX,IAX2,H323 channels without core
-- Fixed various compiler warnings and clean up source tree
-- Preliminary AES Support
-- Fix SIP REINVITE
-- Outbound SIP registration behind NAT using externip
-- More CLI documentation and clean up
-- Pin numbers on MeeMe
-- Dynamic MeetMe conferences are more consistent with static conferences
-- Added channel variables ${HANGUPCAUSE}, ${SIPDOMAIN}, ${TIMESTAMP}, ${ACCONTCODE}
-- ODBC support for logging CDRs
-- Indications for Norway and New Zeland
-- Major redesign of app_voicemail
-- Syslog support
-- Reload logfiles with CLI command 'logger reload' and rotate logs with "logger rotate'
-- Configurable DEBUG, NOTICE, WARNING, ERROR and ast_verbose messages now appear on remote console
-- Properly reaping any zombie processes
-- Added applications SayUnixTime, SetCDRUserField, HasNewVoicemail, ZapScan, Random, ResetCDR, NoCDR
-- Make PRI Hangup Cause available to the dialplan
-- Verify included contexts in extensions.conf
-- Add DESTDIR support for building RPMs and packages
-- Do route lookups on OpenBSD
-- Add support for building on FreeBSD and OS X
-- Add support for PostgreSQL in Voicemail
-- Translate SIP hangup cause to PRI hangup cause where needed
-- Better support for MOH in IAX2
-- Fix SIP problem where channels were not removed on BYE
-- Display codecs by name
-- Remove MySQL and put PGSql instead for licensing reasons
-- Better capability matching in SIP
-- Full IBR4 compliance for chan_zap
-- More flexible CDR handling
-- Distinguish between BUSY and FAILURE on outbound calls
-- Add initial support for SCCP via chan_skinny
-- Better support for Future Group B signaling
Asterisk 0.5.0
-- Retain IAX2 and SIP registrations past shutdown/crash and restart
-- True data mode bridging when possible
-- H.323 build improvements
-- Agent Callback-login support
-- RFC2833 Improvements
-- Add thread debugging
-- Add optional pedantic SIP checking for Pingtel
-- Allow extension names, include context, switch to use global vars.
-- Allow variables in extensions.conf to reference previously defined ones
-- Merge voicemail enhancements (app_voicemail2)
-- Add multiple queueing strategies
-- Merge support for 'T'
-- Allow pending agent calling (Agent/:1)
-- Add groupings to agents.conf
-- Add video support to IAX2
-- Zaptel optimize playback
-- Add video support to SIP
-- Make RTP ports configurable
-- Add RDNIS support to SIP and IAX2
-- Add transfer app (implement in SIP and IAX2)
-- Make voicemail segmentable by context (app_voicemail2)
-- Major restructuring of voicemail (app_voicemail2)
-- Add initial ENUM support
-- Add malloc debugging support
-- Add preliminary Voicetronix support
-- Add iLBC codec
Asterisk 0.4.0
-- Merge and edit Nick's FXO dial support
-- Reengineer SIP registration (outbound)
-- Support call pickup on SIP and compatibly with ZAP
-- Support 302 Redirect on SIP
-- Management interface improvements
-- Add "hint" support
-- Improve call forwarding using new "Local" channel driver.
-- Add "Local" channel
-- Substantial SIP enhancements including retransmissions
-- Enforce case sensitivity on extension/context names
-- Add monitor support (Thanks, Mahmut)
-- Add experimental "trunk" option to IAX2 for high density VoIP
-- Add experimental "debug channel" command
-- Add 'C' flag to dial command to reset call detail record (handy for calling cards)
-- Add NAT and dynamic support to MGCP
-- Allow selection of in-band, out-of-band, or INFO based DTMF
-- Add contributed "*80" support to blacklist numbers (Thanks James!)
-- Add "NAT" option to sip user, peer, friend
-- Add experimental "IAX2" protocol
-- Change special variable "EXTEN-n" to "EXTEN:n" to follow Bash syntax
-- Add "Enhanced" AGI with audio pass-through (voice recognition anyone?)
-- Choose best priority from codec from allow/disallow
-- Reject SIP calls to self
-- Allow SIP registration to provide an alternative contact
-- Make HOLD on SIP make use of asterisk MOH
-- Add supervised transfer (tested with Pingtel only)
-- Allow maxexpirey and defaultexpirey to be runtime configurable for SIP
-- Preliminary codec 13 support (RFC3389)
-- Add app_authenticate for general purpose authentication
-- Optimize RTP and smoother
-- Create special variable "EXTEN-n" where it is extension stripped by n MSD
-- Fix uninitialized frame pointer in channel.c
-- Add global variables support under [globals] of extensions.conf
-- Add macro support (show application Macro)
-- Allow [123-5] etc in extensions
-- Allow format of App(arg1,arg2,...) instead of just App,arg1|arg2 in dialplan
-- Add message waiting indicator to SIP
-- Fix double free bug in channel.c
Asterisk 0.3.0
-- Add fastfoward, rewind, seek, and truncate functions to streams
-- Support registration
-- Add G729 format
-- Permit applications to return a digit indicating new extension
-- Change "SHUTDOWN" to "STOP" in commands
-- SIP "Hold" fixes and VXML URI support
-- New chan_zap with 160 sample chunk size
-- Add DTMF, MF, and Fax tone detector to dsp routines
-- Allow overlap dialing (inbound) on PRI
-- Enable tone detection with PRI
-- Add special information tone detection
-- Add Asterisk DB support
-- Add pulse dialing
-- Re-record all system prompts
-- Change "timelen" to samples for better accuracy
-- Move to editline, eliminating readline dependency
-- Add peer "poke" support to SIP and IAX
-- Add experimental call progress detection
-- Add SIP authentication (digest)
-- Add RDNIS
-- Reroute faxes to "fax" extension
-- Create ISDN/modem group concept
-- Centralize indication
-- Add initial MGCP support
-- SIP debugging cleanup
-- SIP reload
-- SIP commands (show channels, etc)
-- Add optional busy detection
-- Add Visual Message Waiting Indicator (MDMF and SDMF)
-- Add ambiguous extension matching
-- Add *69
-- Major SIP enhancements from SIPit
-- Rewrite of ZAP CLASS features using subchannels
-- Enhanced call parking
-- Add extended outgoing spool support (pbx_spool)
Asterisk 0.2.0
-- Outbound origination API
-- Call management improvements
-- Add Do Not Disturb (*78, *79)
-- Add agents
-- Document variables
-- Add transfer capability on the console
-- Add SpeeX codec translator
-- Add call queues
-- Add setcallerid functionality (AGI, application)
-- Add special variables ${CALLERID}, ${EXTEN}, ${CONTEXT}, ${PRIORITY}
-- Don't echo cancel on pure TDM connections by default
-- Implement Async GOTO
-- Differentiate softhangups
-- Add date/time
Asterisk 0.1.12
-- Fix for Big Endian machines
-- MySQL CDR Engine
-- Various SIP fixes and enhancements
-- Add "zapateller application and arbitrary tone pairs
-- Don't always start at "s"
-- Separate linear mode for pseudo and real
-- Add initial RTP and SIP support (no jitter buffer yet, unknown stability)
-- Add 'h' extension, executed on hangup
-- Add duration timer to message info
-- Add web based voicemail checking ("make webvmail")
-- Add ast_queue_frame function and eliminate frame pipes in most drivers
-- Centralize host access (and possibly future ACL's)
-- Add Caller*ID on PhoneJack (Thanks Nathan)
-- Add "safe_asterisk" wrapper script to auto-restart Asterisk
-- Indicate ringback on chan_phone
-- Add answer confirmation (press '#' to confirm answer)
-- Add distinctive ring support (e.g. Dial,Zap/4r2)
-- Add ANSI/vt100 color support
-- Make parking configurable through parking.conf
-- Fix the empty voicemail problem
-- Add Music On Hold
-- Add ADSI Compiler (app_adsiprog)
-- Extensive DISA re-work to improve tone generation
-- Reset all idle channels every 10 minutes on a PRI
-- Reset channels which are hungup with "channel in use"
-- Implement VNAK support in chan_iax
-- Fix chan_oss to support proper hangups and autoanswer
-- Make shutdown properly hangup channels
-- Add idling capability to chan_zap for idle-net
-- Add "MeetMe" conferencing app (app_meetme)
-- Add timing information to include
Asterisk 0.1.11
-- Add ISDN RAS capability
-- Add stutter dialtone to Chan Zap
-- Add "#include" capability to config files.
-- Add call-forward variable to Chan Zap (*72, *73)
-- Optimize IAX flow when transfer isn't possible
-- Allow transmission of ANI over IAX
Asterisk 0.1.10
-- Make ast_readstring parameter be the max # of digits, not the max size with \0
-- Make up any missing messages on the fly
-- Add support for specific DTMF interruption to saying numbers
-- Add new "u" and "b" options to condense busy/unavail handling
-- Add support for RSA authentication on IAX calls
-- Add support for ADSI compatible CPE
-- Outgoing call queue
-- Remote dialplan fixes for Quicknet
-- Added AGI commands supporting TDD functions (RECEIVE CHAR & TDD MODE)
-- Added TDD support (send/receive text in chan_zap)
-- Fix all strncpy references
-- Implement CSV CDR backend
-- Implement Call Detail Records
Asterisk 0.1.9
-- Implement IAX quelching
-- Allow Caller*ID to be overridden and suggested

63
CREDITS
View File

@@ -1,62 +1,17 @@
=== HARDWARE DONORS ===
* Special thanks to Adtran, Inc, for their donation of an Adtran Atlas,
and TSU 120e to the project. (http://www.adtran.com)
* Thanks to QuickNet Technologies for their donation of an Internet
PhoneJack card to the project. (http://www.quicknet.net)
=== DEVELOPMENT SUPPORT ===
I'd like to thank the following companies for helping fund development of
Asterisk:
Pilosoft, Inc. - for supporting ADSI development in Asterisk
GFS - for supporting ALSA development
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
Gary - Phonejack ADSI (in progress)
Wasim - Hangup detect
=== HARDWARE DONORS ===
* Thanks to QuickNet Technologies for their donation of an Internet
PhoneJack and Linejack card to the project. (http://www.quicknet.net)
=== MISCELLANEOUS PATCHES ===
James Golovich - Innumerable contributions
You can find him and asterisk-perl at http://asterisk.gnuinter.net
Andre Bierwirth - Extension hints and status
Oliver Daudey - ISDN4Linux fixes
Pauline Middelink - ISDN4Linux patches and some general patches.
She can be found at http://www.polyware.nl/~middelink/En/
Jean-Denis Girard - Various contributions from the South Pacific Islands
jd-girard@esoft.pf http://www.esoft.pf
William Jordan / Vonage - MySQL enhancmenets to Voicemail
wjordan@vonage.com
Jac Kersing - Various fixes
Steven Critchfield - Seek and Trunc functions for playback and recording
critch@basesys.com
Jefferson Noxon - app_lookupcidname, app_db, and various other contributions
Klaus-Peter Junghanns - in-band DTMF on SIP and MGCP
Ross Finlayson - Dynamic RTP payload support
Mahmut Fettahlioglu - Audio recording, music-on-hold changes, alaw file
format, and various fixes. Can be contacted at mahmut@oa.com.au
James Dennis - Cisco SIP compatibility patches to work with SIP service
providers. Can be contacted at asterisk@jdennis.net
Tilghman Lesher - - Route lookup code; ast_localtime(), ast_say_date_with_format();
GotoIfTime, Random, SayUnixTime, HasNewVoicemail, and Cut applications,
along with various other patches. http://asterisk.drunkcoder.com/
Jayson Vantuyl - Manager protocol changes, various other bugs.
jvantuyl@computingedge.net
Thorsten Lockert - OpenBSD, FreeBSD ports, making MacOS X port run on 10.3,
dialplan include verification, route lookup on OpenBSD, various other
bugs. tholo@sigmasoft.com
Brian West - ODBC support and Bug Marshaling
William Waites - syslog support, SIP NAT traversal for SIP-UA. ww@styx.org
=== OTHER CONTRIBUTIONS ===
John Todd - Monkey sounds and associated teletorture prompt
* Celera Networks - US Digital
* Adtran, Inc.
=== OTHER SOURCE CODE IN ASTERISK ===

View File

@@ -1,70 +0,0 @@
A PBX is only really useful if you can get calls into it. Of course, you
can use Asterisk with VoIP calls (SIP, H.323, IAX), but you can also talk
to the real PSTN through various cards.
Supported Hardware is divided into two general groups: Zaptel devices and
non-zaptel devices. The Zaptel compatible hardware supports pseudo-TDM
conferencing and all call features through chan_zap, whereas non-zaptel
compatible hardware may have different features.
Zaptel compatible hardware
==========================
-- Digium (Primary author of Asterisk)
http://www.digium.com, http://store.yahoo.com/asteriskpbx
* Wildcard X100P - Single FXO interface connects to Loopstart phone
line
* Wildcard T400P - Quad T1 interface connects to four T1/PRI
interfaces. Supports RBS and PRI voice and PPP, FR, and HDLC 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.
* Wildcard E100P - Single E1 interface connects to a single E1/PRI (or PRA)
interface. Supports PRA/PRI, EuroISDN voice and PPP, FR, HDLC data.
* Wildcard S100U - Single FXS interface connects to a standard analog
telephone.
* Wildcard TDM400P - Quad Modular FXS interface connects to standard
analog telephones.
* Wildcard TE410P - Quad T1/E1 switchable interface. Supports PRI and
RBS signalling, as well as PPP, FR, and HDLC data modes.
Non-zaptel compatible hardware
==============================
-- QuickNet, Inc.
http://www.quicknet.net
* Internet PhoneJack - Single FXS interface. Supports Linux telephony
interface. DSP compression built-in.
* Internet LineJack - Single FXS or FXO interface. Supports Linux
telephony interface.
Miscellaneous other interfaces
==============================
-- ISDN4Linux
http://www.isdn4linux.de/
* Any ISDN terminal adapter supported by isdn4linux should provide
connectivity.
-- ALSA
http://www.alsa-project.org
* Any ALSA compatible full-duplex sound card
-- OSS
http://www.opensound.com
* Any OSS compatible full-duplex sound card

438
Makefile
View File

@@ -11,174 +11,37 @@
# the GNU General Public License
#
.EXPORT_ALL_VARIABLES:
# Create OPTIONS variable
OPTIONS=
OSARCH=$(shell uname -s)
ifeq (${OSARCH},Linux)
PROC=$(shell uname -m)
else
ifeq (${OSARCH},FreeBSD)
PROC=$(shell uname -m)
endif
endif
# Pentium Pro Optimize
#PROC=i686
# Pentium & VIA processors optimize
#PROC=i586
#PROC=k6
#PROC=ppc
PWD=$(shell pwd)
######### More GSM codec optimization
######### Uncomment to enable MMXTM optimizations for x86 architecture CPU's
######### which support MMX instructions. This should be newer pentiums,
######### ppro's, etc, as well as the AMD K6 and K7.
#K6OPT = -DK6OPT
#Tell gcc to optimize the asterisk's code
OPTIMIZE=-O6
#Include debug symbols in the executables (-g) and profiling info (-pg)
DEBUG=-g #-pg
# 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
# Uncomment next one to enable ast_frame tracing (for debugging)
TRACE_FRAMES = #-DTRACE_FRAMES
# Uncomment next one to enable malloc debugging
# You can view malloc debugging with:
# *CLI> show memory allocations [filename]
# *CLI> show memory summary [filename]
#
MALLOC_DEBUG = #-include $(PWD)/include/asterisk/astmm.h
# Where to install asterisk after compiling
# Default -> leave empty
INSTALL_PREFIX=
# Staging directory
# Files are copied here temporarily during the install process
# For example, make DESTDIR=/tmp/asterisk woud put things in
# /tmp/asterisk/etc/asterisk
DESTDIR=
MODULES_DIR=$(INSTALL_PREFIX)/usr/lib/asterisk/modules
AGI_DIR=$(INSTALL_PREFIX)/var/lib/asterisk/agi-bin
# Original busydetect routine
BUSYDETECT = #-DBUSYDETECT
# Improved busydetect routine, comment the previous one if you use this one
BUSYDETECT+= -DBUSYDETECT_MARTIN
# Detect the busy signal looking only at tone lengths
# For example if you have 3 beeps 100ms tone, 100ms silence separated by 500 ms of silence
BUSYDETECT+= #-DBUSYDETECT_TONEONLY
# Inforce the detection of busy singal (get rid of false hangups)
# Don't use together with -DBUSYDETECT_TONEONLY
BUSYDETECT+= #-DBUSYDETECT_COMPARE_TONE_AND_SILENCE
ASTLIBDIR=$(INSTALL_PREFIX)/usr/lib/asterisk
ASTVARLIBDIR=$(INSTALL_PREFIX)/var/lib/asterisk
ASTETCDIR=$(INSTALL_PREFIX)/etc/asterisk
ASTSPOOLDIR=$(INSTALL_PREFIX)/var/spool/asterisk
ASTLOGDIR=$(INSTALL_PREFIX)/var/log/asterisk
ASTHEADERDIR=$(INSTALL_PREFIX)/usr/include/asterisk
ASTCONFPATH=$(ASTETCDIR)/asterisk.conf
ASTBINDIR=$(INSTALL_PREFIX)/usr/bin
ASTSBINDIR=$(INSTALL_PREFIX)/usr/sbin
ASTVARRUNDIR=$(INSTALL_PREFIX)/var/run
MODULES_DIR=$(ASTLIBDIR)/modules
AGI_DIR=$(ASTVARLIBDIR)/agi-bin
# Pentium Pro Optimize
#PROC=i686
# Pentium Optimize
PROC=i586
DEBUG=-g #-pg
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)
#CFLAGS=-pipe -Wall -Wmissing-prototypes -Wmissing-declarations -O6 $(DEBUG) $(INCLUDE) -D_REENTRANT -Werror
CFLAGS=-pipe -Wall -Wmissing-prototypes -Wmissing-declarations -O6 $(DEBUG) $(INCLUDE) -D_REENTRANT
CFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi)
CFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi)
ifeq (${OSARCH},FreeBSD)
CFLAGS+=-pthread
INCLUDE+=-I/usr/local/include
endif
ifeq (${OSARCH},OpenBSD)
CFLAGS+=-pthread
endif
#Uncomment this to use the older DSP routines
#CFLAGS+=-DOLD_DSP_ROUTINES
CFLAGS+=$(shell if [ -f /usr/include/linux/zaptel.h ]; then echo "-DZAPTEL_OPTIMIZATIONS"; fi)
LIBEDIT=editline/libedit.a
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)
ASTERISKVERSION=$(shell if [ -f .version ]; then cat .version; fi)
RPMVERSION=$(shell sed 's/[-\/:]/_/g' .version)
CFLAGS+=-DASTERISK_VERSION=\"$(ASTERISKVERSION)\"
CFLAGS+=-DINSTALL_PREFIX=\"$(INSTALL_PREFIX)\"
CFLAGS+=-DASTETCDIR=\"$(ASTETCDIR)\"
CFLAGS+=-DASTLIBDIR=\"$(ASTLIBDIR)\"
CFLAGS+=-DASTVARLIBDIR=\"$(ASTVARLIBDIR)\"
CFLAGS+=-DASTVARRUNDIR=\"$(ASTVARRUNDIR)\"
CFLAGS+=-DASTSPOOLDIR=\"$(ASTSPOOLDIR)\"
CFLAGS+=-DASTLOGDIR=\"$(ASTLOGDIR)\"
CFLAGS+=-DASTCONFPATH=\"$(ASTCONFPATH)\"
CFLAGS+=-DASTMODDIR=\"$(MODULES_DIR)\"
CFLAGS+=-DASTAGIDIR=\"$(AGI_DIR)\"
CFLAGS+= $(DEBUG_THREADS)
CFLAGS+= $(TRACE_FRAMES)
CFLAGS+= $(MALLOC_DEBUG)
CFLAGS+= $(BUSYDETECT)
CFLAGS+= $(OPTIONS)
# Optional debugging parameters
CFLAGS+= -DDO_CRASH -DDEBUG_THREADS
# Uncomment next one to enable ast_frame tracing (for debugging)
#CLFAGS+= -DTRACE_FRAMES
CFLAGS+=# -fomit-frame-pointer
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
endif
SUBDIRS=channels pbx apps codecs formats agi
LIBS=-ldl -lpthread -lreadline -lncurses -lm
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
ifeq (${OSARCH},Darwin)
OBJS+=poll.o dlfcn.o
ASTLINK=-Wl,-dynamic
SOLINK=-dynamic -bundle -undefined suppress -force_flat_namespace
else
ASTLINK=-Wl,-E
SOLINK=-shared -Xlinker -x
endif
translate.o file.o say.o pbx.o cli.o md5.o \
ulaw.o callerid.o fskmodem.o image.o app.o asterisk.o
CC=gcc
INSTALL=install
@@ -188,149 +51,55 @@ _all: all
@echo " + cannot be run before being installed by +"
@echo " + running: +"
@echo " + +"
@echo " + $(MAKE) install +"
@echo " + make install +"
@echo " +-------------------------------------------+"
all: depend asterisk subdirs
editline/config.h:
cd editline && unset CFLAGS LIBS && ./configure ; \
editline/libedit.a: FORCE
cd editline && unset CFLAGS LIBS && test -f config.h || ./configure
$(MAKE) -C editline libedit.a
db1-ast/libdb1.a: FORCE
@if [ -d db1-ast ]; then \
$(MAKE) -C db1-ast libdb1.a ; \
else \
echo "You need to do a cvs update -d not just cvs update"; \
exit 1; \
fi
ifneq ($(wildcard .depend),)
include .depend
endif
.PHONY: _version
all: asterisk subdirs
_version:
if [ -d CVS ] && ! [ -f .version ]; then echo $(ASTERISKVERSION) > .version; fi
if [ -d CVS ] && ! [ -f .version ]; then echo "CVS-`date +"%D-%T"`" > .version; fi
.version: _version
.y.c:
bison $< --name-prefix=ast_yy -o $@
ast_expr.o: ast_expr.c
cli.o: cli.c build.h
asterisk.o: asterisk.c build.h
ifneq ($(strip $(ASTERISKVERSION)),)
build.h: .version
./make_build_h
else
build.h:
./make_build_h
endif
stdtime/libtime.a: FORCE
@if [ -d stdtime ]; then \
$(MAKE) -C stdtime libtime.a ; \
else \
echo "You need to do a cvs update -d not just cvs update"; \
exit 1; \
fi
asterisk: editline/libedit.a db1-ast/libdb1.a stdtime/libtime.a $(OBJS)
$(CC) $(DEBUG) -o asterisk $(ASTLINK) $(OBJS) $(LIBS) $(LIBEDIT) db1-ast/libdb1.a stdtime/libtime.a
asterisk: _version build.h $(OBJS)
gcc -o asterisk -rdynamic $(OBJS) $(LIBS)
subdirs:
for x in $(SUBDIRS); do $(MAKE) -C $$x || exit 1 ; done
clean:
for x in $(SUBDIRS); do $(MAKE) -C $$x clean || exit 1 ; done
rm -f *.o *.so asterisk .depend
rm -f build.h
rm -f ast_expr.c
@if [ -e editline/Makefile ]; then $(MAKE) -C editline distclean ; fi
$(MAKE) -C db1-ast clean
$(MAKE) -C stdtime clean
rm -f *.o *.so asterisk
rm -f build.h
datafiles: all
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/digits
for x in sounds/digits/*.gsm; do \
if grep -q "^%`basename $$x`%" sounds.txt; then \
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds/digits ; \
else \
echo "No description for $$x"; \
exit 1; \
fi; \
mkdir -p $(INSTALL_PREFIX)/var/lib/asterisk/sounds/digits
for x in sounds/digits/*; do \
install $$x $(INSTALL_PREFIX)/var/lib/asterisk/sounds/digits ; \
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-*; do \
if grep -q "^%`basename $$x`%" sounds.txt; then \
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds ; \
else \
echo "No description for $$x"; \
exit 1; \
fi; \
for x in sounds/vm-* sounds/transfer* sounds/pbx-* sounds/ss-* sounds/beep* sounds/dir-*; do \
install $$x $(INSTALL_PREFIX)/var/lib/asterisk/sounds ; \
done
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/mohmp3
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/images
mkdir -p $(INSTALL_PREFIX)/var/lib/asterisk/images
for x in images/*.jpg; do \
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/images ; \
install $$x $(INSTALL_PREFIX)/var/lib/asterisk/images ; \
done
mkdir -p $(DESTDIR)$(AGI_DIR)
mkdir -p $(AGI_DIR)
update:
@if [ -d CVS ]; then \
echo "Updating from CVS..." ; \
cvs -q update -Pd; \
rm -f .version; \
else \
echo "Not CVS"; \
fi
bininstall: all
mkdir -p $(DESTDIR)$(MODULES_DIR)
mkdir -p $(DESTDIR)$(ASTSBINDIR)
mkdir -p $(DESTDIR)$(ASTETCDIR)
mkdir -p $(DESTDIR)$(ASTBINDIR)
mkdir -p $(DESTDIR)$(ASTSBINDIR)
mkdir -p $(DESTDIR)$(ASTVARRUNDIR)
mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/voicemail
install -m 755 asterisk $(DESTDIR)$(ASTSBINDIR)/
install -m 755 contrib/scripts/astgenkey $(DESTDIR)$(ASTSBINDIR)/
if [ ! -f $(DESTDIR)$(ASTSBINDIR)/safe_asterisk ]; then \
install -m 755 contrib/scripts/safe_asterisk $(DESTDIR)$(ASTSBINDIR)/ ;\
fi
install: all datafiles
mkdir -p $(MODULES_DIR)
mkdir -p $(INSTALL_PREFIX)/usr/sbin
install -m 755 asterisk $(INSTALL_PREFIX)/usr/sbin/
for x in $(SUBDIRS); do $(MAKE) -C $$x install || exit 1 ; done
install -d $(DESTDIR)$(ASTHEADERDIR)
install -m 644 include/asterisk/*.h $(DESTDIR)$(ASTHEADERDIR)
rm -f $(DESTDIR)$(ASTVARLIBDIR)/sounds/vm
rm -f $(DESTDIR)$(ASTVARLIBDIR)/sounds/voicemail
if [ ! -h $(DESTDIR)$(ASTSPOOLDIR)/vm ] && [ -d $(DESTDIR)$(ASTSPOOLDIR)/vm ]; then \
mv $(DESTDIR)$(ASTSPOOLDIR)/vm $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default; \
else \
mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default; \
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
install -m 644 keys/iaxtel.pub $(DESTDIR)$(ASTVARLIBDIR)/keys
( cd $(DESTDIR)$(ASTVARLIBDIR)/sounds ; ln -s $(ASTSPOOLDIR)/vm . )
( cd $(DESTDIR)$(ASTVARLIBDIR)/sounds ; ln -s $(ASTSPOOLDIR)/voicemail . )
install -d $(INSTALL_PREFIX)/usr/include/asterisk
install include/asterisk/*.h $(INSTALL_PREFIX)/usr/include/asterisk
rm -f $(INSTALL_PREFIX)/var/lib/asterisk/sounds/vm
mkdir -p $(INSTALL_PREFIX)/var/spool/asterisk/vm
rm -f $(INSTALL_PREFIX)/usr/lib/asterisk/modules/chan_ixj.so
rm -f $(INSTALL_PREFIX)/usr/lib/asterisk/modules/chan_tor.so
mkdir -p $(INSTALL_PREFIX)/var/lib/asterisk/sounds
( cd $(INSTALL_PREFIX)/var/lib/asterisk/sounds ; ln -s ../../../spool/asterisk/vm . )
@echo " +---- Asterisk Installation Complete -------+"
@echo " + +"
@echo " + YOU MUST READ THE SECURITY DOCUMENT +"
@@ -340,88 +109,41 @@ bininstall: all
@echo " + configuration files (overwriting any +"
@echo " + existing config files), run: +"
@echo " + +"
@echo " + $(MAKE) samples +"
@echo " + make samples +"
@echo " + +"
@echo " +----------------- or ---------------------+"
@echo " + +"
@echo " + You can go ahead and install the asterisk +"
@echo " + program documentation now or later run: +"
@echo " + +"
@echo " + $(MAKE) progdocs +"
@echo " + make progdocs +"
@echo " + +"
@echo " + **Note** This requires that you have +"
@echo " + doxygen installed on your local system +"
@echo " +-------------------------------------------+"
install: all datafiles bininstall
upgrade: all bininstall
adsi: all
mkdir -p $(DESTDIR)$(ASTETCDIR)
for x in configs/*.adsi; do \
if ! [ -f $(DESTDIR)$(ASTETCDIRX)/$$x ]; then \
install -m 644 $$x $(DESTDIR)$(ASTETCDIR)/`basename $$x` ; \
fi ; \
done
samples: all datafiles adsi
mkdir -p $(DESTDIR)$(ASTETCDIR)
samples: all datafiles
mkdir -p $(INSTALL_PREFIX)/etc/asterisk
for x in configs/*.sample; do \
if [ -f $(DESTDIR)$(ASTETCDIR)/`basename $$x .sample` ]; then \
mv -f $(DESTDIR)$(ASTETCDIR)/`basename $$x .sample` $(DESTDIR)$(ASTETCDIR)/`basename $$x .sample`.old ; \
if [ -f $(INSTALL_PREFIX)/etc/asterisk/`basename $$x .sample` ]; then \
mv -f $(INSTALL_PREFIX)/etc/asterisk/`basename $$x .sample` $(INSTALL_PREFIX)/etc/asterisk/`basename $$x .sample`.old ; \
fi ; \
install -m 644 $$x $(DESTDIR)$(ASTETCDIR)/`basename $$x .sample` ;\
install $$x $(INSTALL_PREFIX)/etc/asterisk/`basename $$x .sample` ;\
done
echo "[directories]" > $(DESTDIR)$(ASTETCDIR)/asterisk.conf
echo "astetcdir => $(ASTETCDIR)" >> $(DESTDIR)$(ASTETCDIR)/asterisk.conf
echo "astmoddir => $(MODULES_DIR)" >> $(DESTDIR)$(ASTETCDIR)/asterisk.conf
echo "astvarlibdir => $(ASTVARLIBDIR)" >> $(DESTDIR)$(ASTETCDIR)/asterisk.conf
echo "astagidir => $(AGI_DIR)" >> $(DESTDIR)$(ASTETCDIR)/asterisk.conf
echo "astspooldir => $(ASTSPOOLDIR)" >> $(DESTDIR)$(ASTETCDIR)/asterisk.conf
echo "astrundir => $(ASTVARRUNDIR)" >> $(DESTDIR)$(ASTETCDIR)/asterisk.conf
echo "astlogdir => $(ASTLOGDIR)" >> $(DESTDIR)$(ASTETCDIR)/asterisk.conf
for x in sounds/demo-*; do \
if grep -q "^%`basename $$x`%" sounds.txt; then \
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds ; \
else \
echo "No description for $$x"; \
exit 1; \
fi; \
install $$x $(INSTALL_PREFIX)/var/lib/asterisk/sounds; \
done
for x in sounds/*.mp3; do \
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/mohmp3 ; \
done
mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/INBOX
:> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/unavail.gsm
mkdir -p $(INSTALL_PREFIX)/var/spool/asterisk/vm/1234/INBOX
:> $(INSTALL_PREFIX)/var/lib/asterisk/sounds/vm/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 ; \
cat $(INSTALL_PREFIX)/var/lib/asterisk/sounds/$$x.gsm >> $(INSTALL_PREFIX)/var/lib/asterisk/sounds/vm/1234/unavail.gsm ; \
done
:> $(DESTDIR)$(ASTVARLIBDIR)/sounds/voicemail/default/1234/busy.gsm
:> $(INSTALL_PREFIX)/var/lib/asterisk/sounds/vm/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 ; \
cat $(INSTALL_PREFIX)/var/lib/asterisk/sounds/$$x.gsm >> $(INSTALL_PREFIX)/var/lib/asterisk/sounds/vm/1234/busy.gsm ; \
done
webvmail:
@[ -d $(DESTDIR)$(HTTPDIR) ] || ( echo "No HTTP directory" && exit 1 )
@[ -d $(DESTDIR)$(HTTPDIR)/html ] || ( echo "No http directory" && exit 1 )
@[ -d $(DESTDIR)$(HTTPDIR)/cgi-bin ] || ( echo "No cgi-bin directory" && exit 1 )
install -m 4755 -o root -g root contrib/scripts/vmail.cgi $(DESTDIR)$(HTTPDIR)/cgi-bin/vmail.cgi
mkdir -p $(DESTDIR)$(HTTPDIR)/html/_asterisk
for x in images/*.gif; do \
install -m 644 $$x $(DESTDIR)$(HTTPDIR)/html/_asterisk/; \
done
@echo " +--------- Asterisk Web Voicemail ----------+"
@echo " + +"
@echo " + Asterisk Web Voicemail is installed in +"
@echo " + your cgi-bin directory. IT USES A SETUID +"
@echo " + ROOT PERL SCRIPT, SO IF YOU DON'T LIKE +"
@echo " + THAT, UNINSTALL IT! +"
@echo " + +"
@echo " +-------------------------------------------+"
mailbox:
./contrib/scripts/addmailbox
./addmailbox
rpm: __rpm
@@ -429,34 +151,16 @@ rpm: __rpm
__rpm: _version
rm -rf /tmp/asterisk ; \
mkdir -p /tmp/asterisk/redhat/RPMS/i386 ; \
$(MAKE) DESTDIR=/tmp/asterisk install ; \
$(MAKE) DESTDIR=/tmp/asterisk samples ; \
make INSTALL_PREFIX=/tmp/asterisk install ; \
make INSTALL_PREFIX=/tmp/asterisk samples ; \
mkdir -p /tmp/asterisk/etc/rc.d/init.d ; \
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
cp -f redhat/rpmrc /tmp/asterisk/ ; \
cp -f redhat/rpmmacros /tmp/asterisk/ ; \
sed "s/Version:/Version: $(RPMVERSION)/g" redhat/asterisk.spec > /tmp/asterisk/asterisk.spec ; \
rpm --rcfile /usr/lib/rpm/rpmrc:/tmp/asterisk/rpmrc -bb /tmp/asterisk/asterisk.spec ; \
mv /tmp/asterisk/redhat/RPMS/i386/asterisk* ./ ; \
rm -rf /tmp/asterisk
progdocs:
doxygen contrib/asterisk-ng-doxygen
config:
if [ -d /etc/rc.d/init.d ]; then \
install -m 755 contrib/init.d/rc.redhat.asterisk /etc/rc.d/init.d/asterisk; \
/sbin/chkconfig --add asterisk; \
elif [ -d /etc/init.d ]; then \
install -m 755 init.asterisk /etc/init.d/asterisk; \
fi
dont-optimize:
$(MAKE) OPTIMIZE= K6OPT= install
valgrind: dont-optimize
depend: .depend
for x in $(SUBDIRS); do $(MAKE) -C $$x depend || exit 1 ; done
.depend:
./mkdep ${CFLAGS} `ls *.c`
FORCE:
doxygen asterisk-ng-doxygen

38
README
View File

@@ -1,6 +1,6 @@
The Asterisk Open Source PBX
by Mark Spencer <markster@digium.com>
Copyright (C) 2001-2004 Digium
by Mark Spencer <markster@linux-support.net>
Copyright (C) 2001, Linux Support Services, Inc.
================================================================
* SECURITY
It is imperative that you read and fully understand the contents of
@@ -12,40 +12,35 @@ sense, middleware between Internet and telephony channels on the bottom,
and Internet and telephony applications at the top. For more information
on the project itself, please visit the Asterisk home page at:
http://www.asterisk.org
http://www.asteriskpbx.com
* 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 discression,
the ability for companies, individuals, or organizations to create proprietary
Linux Support Services, Inc. retains copyright to all 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
umbrella, or are distributed under more flexible licenses than GPL.
umbrella, or are distributed under more flexible licenses than GPL. At
this time (5/21/2001) the only component of Asterisk which is covered
under GPL and not under our Copyright is the Xing MP3 decoder.
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 excemption that we do).
Specific permission is also granted to OpenSSL and OpenH323 to link to
Asterisk.
If you have any questions, whatsoever, regarding our licensing policy,
please contact us.
Modules that are GPL-licensed and not available under Digium's
licensing scheme are added to the Asterisk-addons CVS module.
* REQUIRED COMPONENTS
== 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
as well.
as well.
* GETTING STARTED
@@ -53,10 +48,9 @@ as well.
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)
* Full Duplex Sound Card supported by Linux
* Adtran Atlas 800 Plus
* QuickNet Internet PhoneJack
* Full Duplex Sound Card supported by Linux
* ISDN4Linux compatible ISDN card
* Tormenta Dual T1 card (www.bsdtelephony.com.mx)
@@ -133,13 +127,7 @@ from the variables specified above.
* MORE INFORMATION
See the doc directory for more documentation.
Finally, you may wish to visit the web site and join the mailing list if
you're interested in getting more information.
http://www.asterisk.org/index.php?menu=support
Welcome to the growing worldwide community of Asterisk users!
Mark Spencer
Mark

View File

@@ -36,6 +36,3 @@ include => default
exten => 6123,Dial,Tor/1
DON'T FORGET TO TAKE THE DEMO CONTEXT OUT OF YOUR DEFAULT CONTEXT. There
isn't really a security reason, it just will keep people from wanting to
play with your asterisk setup remotely.

331
acl.c
View File

@@ -1,331 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Various sorts of access control
*
* 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 <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <asterisk/acl.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <net/if.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <sys/ioctl.h>
#ifdef __OpenBSD__
#include <fcntl.h>
#include <net/route.h>
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 */
struct in_addr netaddr;
struct in_addr netmask;
int sense;
struct ast_ha *next;
};
/* Default IP - if not otherwise set, don't breathe garbage */
static struct in_addr __ourip = { 0x00000000 };
struct my_ifreq {
char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "eth0", "ppp0", etc. */
struct sockaddr_in ifru_addr;
};
void ast_free_ha(struct ast_ha *ha)
{
struct ast_ha *hal;
while(ha) {
hal = ha;
ha = ha->next;
free(hal);
}
}
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;
char tmp[256] = "";
struct ast_ha *prev = NULL;
struct ast_ha *ret;
int x,z;
unsigned int y;
ret = path;
while(path) {
prev = path;
path = path->next;
}
if (ha) {
strncpy(tmp, stuff, sizeof(tmp) - 1);
nm = strchr(tmp, '/');
if (!nm)
nm = "255.255.255.255";
else {
*nm = '\0';
nm++;
}
if (!strchr(nm, '.')) {
if ((sscanf(nm, "%i", &x) == 1) && (x >= 0) && (x <= 32)) {
y = 0;
for (z=0;z<x;z++) {
y >>= 1;
y |= 0x80000000;
}
ha->netmask.s_addr = htonl(y);
}
} else if (!inet_aton(nm, &ha->netmask)) {
ast_log(LOG_WARNING, "%s not a valid netmask\n", nm);
free(ha);
return path;
}
if (!inet_aton(tmp, &ha->netaddr)) {
ast_log(LOG_WARNING, "%s not a valid IP\n", tmp);
free(ha);
return path;
}
ha->netaddr.s_addr &= ha->netmask.s_addr;
if (!strncasecmp(sense, "p", 1)) {
ha->sense = AST_SENSE_ALLOW;
} else {
ha->sense = AST_SENSE_DENY;
}
ha->next = NULL;
if (prev)
prev->next = ha;
else
ret = ha;
}
return ret;
}
int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
{
/* Start optimistic */
int res = AST_SENSE_ALLOW;
while(ha) {
/* 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))
res = ha->sense;
ha = ha->next;
}
return res;
}
int ast_get_ip(struct sockaddr_in *sin, char *value)
{
struct hostent *hp;
hp = gethostbyname(value);
if (hp) {
memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
} else {
ast_log(LOG_WARNING, "Unable to lookup '%s'\n", value);
return -1;
}
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;
struct my_ifreq ifreq;
memset(&ifreq, 0, sizeof(ifreq));
strncpy(ifreq.ifrn_name,iface,sizeof(ifreq.ifrn_name) - 1);
mysock = socket(PF_INET,SOCK_DGRAM,IPPROTO_IP);
res = ioctl(mysock,SIOCGIFADDR,&ifreq);
close(mysock);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to get IP of %s: %s\n", iface, strerror(errno));
memcpy((char *)address,(char *)&__ourip,sizeof(__ourip));
return -1;
} else {
memcpy((char *)address,(char *)&ifreq.ifru_addr.sin_addr,sizeof(ifreq.ifru_addr.sin_addr));
return 0;
}
}
int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
{
#ifdef __OpenBSD__
struct sockaddr_in *sin;
struct sockaddr *sa;
struct {
struct rt_msghdr m_rtm;
char m_space[512];
} m_rtmsg;
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 */
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_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, 0)) < 0) {
ast_log(LOG_ERROR, "Error opening routing socket\n");
return -1;
}
flags = fcntl(s, F_GETFL);
fcntl(s, F_SETFL, flags | O_NONBLOCK);
if (write(s, (char *)&m_rtmsg, m_rtmsg.m_rtm.rtm_msglen) < 0) {
ast_log(LOG_ERROR, "Error writing to routing socket: %s\n", strerror(errno));
close(s);
return -1;
}
do {
l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
} 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");
close(s);
return -1;
}
close(s);
if (m_rtmsg.m_rtm.rtm_version != RTM_VERSION) {
ast_log(LOG_ERROR, "Unsupported route socket protocol version\n");
return -1;
}
if (m_rtmsg.m_rtm.rtm_msglen != l)
ast_log(LOG_WARNING, "Message length mismatch, in packet %d, returned %d\n",
m_rtmsg.m_rtm.rtm_msglen, l);
if (m_rtmsg.m_rtm.rtm_errno) {
ast_log(LOG_ERROR, "RTM_GET got %s (%d)\n",
strerror(m_rtmsg.m_rtm.rtm_errno), m_rtmsg.m_rtm.rtm_errno);
return -1;
}
cp = (char *)m_rtmsg.m_space;
if (m_rtmsg.m_rtm.rtm_addrs)
for (i = 1; i; i <<= 1)
if (m_rtmsg.m_rtm.rtm_addrs & i) {
sa = (struct sockaddr *)cp;
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, inet_ntoa(*us));
return 0;
}
cp += sa->sa_len > 0 ?
(1 + ((sa->sa_len - 1) | (sizeof(long) - 1))) :
sizeof(long);
}
ast_log(LOG_DEBUG, "No route found for address %s!\n", p);
return -1;
#else
FILE *PROC;
unsigned int remote_ip;
int res = 1;
char line[256];
remote_ip = them->s_addr;
PROC = fopen("/proc/net/route","r");
if (!PROC) {
bzero(us,sizeof(struct in_addr));
return -1;
}
/* First line contains headers */
fgets(line,sizeof(line),PROC);
while (!feof(PROC)) {
char iface[8];
unsigned int dest, gateway, mask;
int i,fieldnum;
char *fields[40];
fgets(line,sizeof(line),PROC);
fieldnum = 0;
for (i=0;i<sizeof(line);i++) {
char *offset;
fields[fieldnum++] = line + i;
offset = strchr(line + i,'\t');
if (offset == NULL) {
/* Exit loop */
break;
} else if (fieldnum >= 9) {
/* Short-circuit: can't break at 8, since the end of field 7 is figured when fieldnum=8 */
break;
} else {
*offset = '\0';
i = offset - line;
}
}
sscanf(fields[0],"%s",iface);
sscanf(fields[1],"%x",&dest);
sscanf(fields[2],"%x",&gateway);
sscanf(fields[7],"%x",&mask);
#if 0
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;
}
}
fclose(PROC);
if (res == 1) {
ast_log(LOG_WARNING, "Yikes! No default route?!!\n");
bzero(us,sizeof(struct in_addr));
return -2;
} else if (res) {
/* We've already warned in subroutine */
return -1;
}
return 0;
#endif
}

20
addmailbox Normal file
View File

@@ -0,0 +1,20 @@
#!/bin/sh
VMHOME=/var/spool/asterisk/vm
SNDHOME=/var/lib/asterisk/sounds
echo -n "Enter mailbox number: "
read mailbox
mkdir -p ${VMHOME}/${mailbox}
mkdir -p ${VMHOME}/${mailbox}/INBOX
cat ${SNDHOME}/vm-theperson.gsm > ${VMHOME}/${mailbox}/unavail.gsm
cat ${SNDHOME}/vm-theperson.gsm > ${VMHOME}/${mailbox}/busy.gsm
cat ${SNDHOME}/vm-extension.gsm > ${VMHOME}/${mailbox}/greet.gsm
nums=`echo $mailbox | sed 's/./ \0/g'`
for x in $nums; do
cat ${SNDHOME}/digits/${x}.gsm >> ${VMHOME}/${mailbox}/unavail.gsm
cat ${SNDHOME}/digits/${x}.gsm >> ${VMHOME}/${mailbox}/busy.gsm
cat ${SNDHOME}/digits/${x}.gsm >> ${VMHOME}/${mailbox}/greet.gsm
done
cat ${SNDHOME}/vm-isunavail.gsm >> ${VMHOME}/${mailbox}/unavail.gsm
cat ${SNDHOME}/vm-isonphone.gsm >> ${VMHOME}/${mailbox}/busy.gsm

View File

@@ -1,311 +0,0 @@
/*
---------------------------------------------------------------------------
Copyright (c) 2003, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 26/08/2003
This file contains the code for implementing encryption and decryption
for AES (Rijndael) for block and key sizes of 16, 24 and 32 bytes. It
can optionally be replaced by code written in assembler using NASM. For
further details see the file aesopt.h
*/
#include "aesopt.h"
#if defined(__cplusplus)
extern "C"
{
#endif
#define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c])
#define so(y,x,c) word_out(y, c, s(x,c))
#if defined(ARRAYS)
#define locals(y,x) x[4],y[4]
#else
#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3
#endif
#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \
s(y,2) = s(x,2); s(y,3) = s(x,3);
#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3)
#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3)
#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3)
#if defined(ENCRYPTION) && !defined(AES_ASM)
/* Visual C++ .Net v7.1 provides the fastest encryption code when using
Pentium optimiation with small code but this is poor for decryption
so we need to control this with the following VC++ pragmas
*/
#if defined(_MSC_VER)
#pragma optimize( "s", on )
#endif
/* Given the column (c) of the output state variable, the following
macros give the input state variables which are needed in its
computation for each row (r) of the state. All the alternative
macros give the same end values but expand into different ways
of calculating these values. In particular the complex macro
used for dynamically variable block sizes is designed to expand
to a compile time constant whenever possible but will expand to
conditional clauses on some branches (I am grateful to Frank
Yellin for this construction)
*/
#define fwd_var(x,r,c)\
( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
: r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\
: r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
: ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2)))
#if defined(FT4_SET)
#undef dec_fmvars
#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c))
#elif defined(FT1_SET)
#undef dec_fmvars
#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(f,n),fwd_var,rf1,c))
#else
#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ fwd_mcol(no_table(x,t_use(s,box),fwd_var,rf1,c)))
#endif
#if defined(FL4_SET)
#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c))
#elif defined(FL1_SET)
#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(f,l),fwd_var,rf1,c))
#else
#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(s,box),fwd_var,rf1,c))
#endif
aes_rval aes_encrypt(const void *in_blk, void *out_blk, const aes_encrypt_ctx cx[1])
{ aes_32t locals(b0, b1);
const aes_32t *kp = cx->ks;
#ifdef dec_fmvars
dec_fmvars; /* declare variables for fwd_mcol() if needed */
#endif
aes_32t nr = (kp[45] ^ kp[52] ^ kp[53] ? kp[52] : 14);
#ifdef AES_ERR_CHK
if( (nr != 10 || !(kp[0] | kp[3] | kp[4]))
&& (nr != 12 || !(kp[0] | kp[5] | kp[6]))
&& (nr != 14 || !(kp[0] | kp[7] | kp[8])) )
return aes_error;
#endif
state_in(b0, in_blk, kp);
#if (ENC_UNROLL == FULL)
switch(nr)
{
case 14:
round(fwd_rnd, b1, b0, kp + 1 * N_COLS);
round(fwd_rnd, b0, b1, kp + 2 * N_COLS);
kp += 2 * N_COLS;
case 12:
round(fwd_rnd, b1, b0, kp + 1 * N_COLS);
round(fwd_rnd, b0, b1, kp + 2 * N_COLS);
kp += 2 * N_COLS;
case 10:
round(fwd_rnd, b1, b0, kp + 1 * N_COLS);
round(fwd_rnd, b0, b1, kp + 2 * N_COLS);
round(fwd_rnd, b1, b0, kp + 3 * N_COLS);
round(fwd_rnd, b0, b1, kp + 4 * N_COLS);
round(fwd_rnd, b1, b0, kp + 5 * N_COLS);
round(fwd_rnd, b0, b1, kp + 6 * N_COLS);
round(fwd_rnd, b1, b0, kp + 7 * N_COLS);
round(fwd_rnd, b0, b1, kp + 8 * N_COLS);
round(fwd_rnd, b1, b0, kp + 9 * N_COLS);
round(fwd_lrnd, b0, b1, kp +10 * N_COLS);
}
#else
#if (ENC_UNROLL == PARTIAL)
{ aes_32t rnd;
for(rnd = 0; rnd < (nr >> 1) - 1; ++rnd)
{
kp += N_COLS;
round(fwd_rnd, b1, b0, kp);
kp += N_COLS;
round(fwd_rnd, b0, b1, kp);
}
kp += N_COLS;
round(fwd_rnd, b1, b0, kp);
#else
{ aes_32t rnd;
for(rnd = 0; rnd < nr - 1; ++rnd)
{
kp += N_COLS;
round(fwd_rnd, b1, b0, kp);
l_copy(b0, b1);
}
#endif
kp += N_COLS;
round(fwd_lrnd, b0, b1, kp);
}
#endif
state_out(out_blk, b0);
#ifdef AES_ERR_CHK
return aes_good;
#endif
}
#endif
#if defined(DECRYPTION) && !defined(AES_ASM)
/* Visual C++ .Net v7.1 provides the fastest encryption code when using
Pentium optimiation with small code but this is poor for decryption
so we need to control this with the following VC++ pragmas
*/
#if defined(_MSC_VER)
#pragma optimize( "t", on )
#endif
/* Given the column (c) of the output state variable, the following
macros give the input state variables which are needed in its
computation for each row (r) of the state. All the alternative
macros give the same end values but expand into different ways
of calculating these values. In particular the complex macro
used for dynamically variable block sizes is designed to expand
to a compile time constant whenever possible but will expand to
conditional clauses on some branches (I am grateful to Frank
Yellin for this construction)
*/
#define inv_var(x,r,c)\
( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
: r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\
: r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
: ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0)))
#if defined(IT4_SET)
#undef dec_imvars
#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c))
#elif defined(IT1_SET)
#undef dec_imvars
#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c))
#else
#define inv_rnd(y,x,k,c) (s(y,c) = inv_mcol((k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c)))
#endif
#if defined(IL4_SET)
#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c))
#elif defined(IL1_SET)
#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c))
#else
#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c))
#endif
aes_rval aes_decrypt(const void *in_blk, void *out_blk, const aes_decrypt_ctx cx[1])
{ aes_32t locals(b0, b1);
#ifdef dec_imvars
dec_imvars; /* declare variables for inv_mcol() if needed */
#endif
aes_32t nr = (cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] ? cx->ks[52] : 14);
const aes_32t *kp = cx->ks + nr * N_COLS;
#ifdef AES_ERR_CHK
if( (nr != 10 || !(cx->ks[0] | cx->ks[3] | cx->ks[4]))
&& (nr != 12 || !(cx->ks[0] | cx->ks[5] | cx->ks[6]))
&& (nr != 14 || !(cx->ks[0] | cx->ks[7] | cx->ks[8])) )
return aes_error;
#endif
state_in(b0, in_blk, kp);
#if (DEC_UNROLL == FULL)
switch(nr)
{
case 14:
round(inv_rnd, b1, b0, kp - 1 * N_COLS);
round(inv_rnd, b0, b1, kp - 2 * N_COLS);
kp -= 2 * N_COLS;
case 12:
round(inv_rnd, b1, b0, kp - 1 * N_COLS);
round(inv_rnd, b0, b1, kp - 2 * N_COLS);
kp -= 2 * N_COLS;
case 10:
round(inv_rnd, b1, b0, kp - 1 * N_COLS);
round(inv_rnd, b0, b1, kp - 2 * N_COLS);
round(inv_rnd, b1, b0, kp - 3 * N_COLS);
round(inv_rnd, b0, b1, kp - 4 * N_COLS);
round(inv_rnd, b1, b0, kp - 5 * N_COLS);
round(inv_rnd, b0, b1, kp - 6 * N_COLS);
round(inv_rnd, b1, b0, kp - 7 * N_COLS);
round(inv_rnd, b0, b1, kp - 8 * N_COLS);
round(inv_rnd, b1, b0, kp - 9 * N_COLS);
round(inv_lrnd, b0, b1, kp - 10 * N_COLS);
}
#else
#if (DEC_UNROLL == PARTIAL)
{ aes_32t rnd;
for(rnd = 0; rnd < (nr >> 1) - 1; ++rnd)
{
kp -= N_COLS;
round(inv_rnd, b1, b0, kp);
kp -= N_COLS;
round(inv_rnd, b0, b1, kp);
}
kp -= N_COLS;
round(inv_rnd, b1, b0, kp);
#else
{ aes_32t rnd;
for(rnd = 0; rnd < nr - 1; ++rnd)
{
kp -= N_COLS;
round(inv_rnd, b1, b0, kp);
l_copy(b0, b1);
}
#endif
kp -= N_COLS;
round(inv_lrnd, b0, b1, kp);
}
#endif
state_out(out_blk, b0);
#ifdef AES_ERR_CHK
return aes_good;
#endif
}
#endif
#if defined(__cplusplus)
}
#endif

463
aeskey.c
View File

@@ -1,463 +0,0 @@
/*
---------------------------------------------------------------------------
Copyright (c) 2003, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 26/08/2003
This file contains the code for implementing the key schedule for AES
(Rijndael) for block and key sizes of 16, 24, and 32 bytes. See aesopt.h
for further details including optimisation.
*/
#include "aesopt.h"
#if defined(__cplusplus)
extern "C"
{
#endif
/* Initialise the key schedule from the user supplied key. The key
length can be specified in bytes, with legal values of 16, 24
and 32, or in bits, with legal values of 128, 192 and 256. These
values correspond with Nk values of 4, 6 and 8 respectively.
The following macros implement a single cycle in the key
schedule generation process. The number of cycles needed
for each cx->n_col and nk value is:
nk = 4 5 6 7 8
------------------------------
cx->n_col = 4 10 9 8 7 7
cx->n_col = 5 14 11 10 9 9
cx->n_col = 6 19 15 12 11 11
cx->n_col = 7 21 19 16 13 14
cx->n_col = 8 29 23 19 17 14
*/
#define ke4(k,i) \
{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+5] = ss[1] ^= ss[0]; \
k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \
}
#define kel4(k,i) \
{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+5] = ss[1] ^= ss[0]; \
k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \
}
#define ke6(k,i) \
{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 7] = ss[1] ^= ss[0]; \
k[6*(i)+ 8] = ss[2] ^= ss[1]; k[6*(i)+ 9] = ss[3] ^= ss[2]; \
k[6*(i)+10] = ss[4] ^= ss[3]; k[6*(i)+11] = ss[5] ^= ss[4]; \
}
#define kel6(k,i) \
{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 7] = ss[1] ^= ss[0]; \
k[6*(i)+ 8] = ss[2] ^= ss[1]; k[6*(i)+ 9] = ss[3] ^= ss[2]; \
}
#define ke8(k,i) \
{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 9] = ss[1] ^= ss[0]; \
k[8*(i)+10] = ss[2] ^= ss[1]; k[8*(i)+11] = ss[3] ^= ss[2]; \
k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); k[8*(i)+13] = ss[5] ^= ss[4]; \
k[8*(i)+14] = ss[6] ^= ss[5]; k[8*(i)+15] = ss[7] ^= ss[6]; \
}
#define kel8(k,i) \
{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 9] = ss[1] ^= ss[0]; \
k[8*(i)+10] = ss[2] ^= ss[1]; k[8*(i)+11] = ss[3] ^= ss[2]; \
}
#if defined(ENCRYPTION_KEY_SCHEDULE)
#if defined(AES_128) || defined(AES_VAR)
aes_rval aes_encrypt_key128(const void *in_key, aes_encrypt_ctx cx[1])
{ aes_32t ss[4];
cx->ks[0] = ss[0] = word_in(in_key, 0);
cx->ks[1] = ss[1] = word_in(in_key, 1);
cx->ks[2] = ss[2] = word_in(in_key, 2);
cx->ks[3] = ss[3] = word_in(in_key, 3);
#if ENC_UNROLL == NONE
{ aes_32t i;
for(i = 0; i < ((11 * N_COLS - 1) / 4); ++i)
ke4(cx->ks, i);
}
#else
ke4(cx->ks, 0); ke4(cx->ks, 1);
ke4(cx->ks, 2); ke4(cx->ks, 3);
ke4(cx->ks, 4); ke4(cx->ks, 5);
ke4(cx->ks, 6); ke4(cx->ks, 7);
ke4(cx->ks, 8); kel4(cx->ks, 9);
#endif
/* cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] is zero for a 256 bit */
/* key and must be non-zero for 128 and 192 bits keys */
cx->ks[53] = cx->ks[45] = 0;
cx->ks[52] = 10;
#ifdef AES_ERR_CHK
return aes_good;
#endif
}
#endif
#if defined(AES_192) || defined(AES_VAR)
aes_rval aes_encrypt_key192(const void *in_key, aes_encrypt_ctx cx[1])
{ aes_32t ss[6];
cx->ks[0] = ss[0] = word_in(in_key, 0);
cx->ks[1] = ss[1] = word_in(in_key, 1);
cx->ks[2] = ss[2] = word_in(in_key, 2);
cx->ks[3] = ss[3] = word_in(in_key, 3);
cx->ks[4] = ss[4] = word_in(in_key, 4);
cx->ks[5] = ss[5] = word_in(in_key, 5);
#if ENC_UNROLL == NONE
{ aes_32t i;
for(i = 0; i < (13 * N_COLS - 1) / 6; ++i)
ke6(cx->ks, i);
}
#else
ke6(cx->ks, 0); ke6(cx->ks, 1);
ke6(cx->ks, 2); ke6(cx->ks, 3);
ke6(cx->ks, 4); ke6(cx->ks, 5);
ke6(cx->ks, 6); kel6(cx->ks, 7);
#endif
/* cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] is zero for a 256 bit */
/* key and must be non-zero for 128 and 192 bits keys */
cx->ks[53] = cx->ks[45];
cx->ks[52] = 12;
#ifdef AES_ERR_CHK
return aes_good;
#endif
}
#endif
#if defined(AES_256) || defined(AES_VAR)
aes_rval aes_encrypt_key256(const void *in_key, aes_encrypt_ctx cx[1])
{ aes_32t ss[8];
cx->ks[0] = ss[0] = word_in(in_key, 0);
cx->ks[1] = ss[1] = word_in(in_key, 1);
cx->ks[2] = ss[2] = word_in(in_key, 2);
cx->ks[3] = ss[3] = word_in(in_key, 3);
cx->ks[4] = ss[4] = word_in(in_key, 4);
cx->ks[5] = ss[5] = word_in(in_key, 5);
cx->ks[6] = ss[6] = word_in(in_key, 6);
cx->ks[7] = ss[7] = word_in(in_key, 7);
#if ENC_UNROLL == NONE
{ aes_32t i;
for(i = 0; i < (15 * N_COLS - 1) / 8; ++i)
ke8(cx->ks, i);
}
#else
ke8(cx->ks, 0); ke8(cx->ks, 1);
ke8(cx->ks, 2); ke8(cx->ks, 3);
ke8(cx->ks, 4); ke8(cx->ks, 5);
kel8(cx->ks, 6);
#endif
#ifdef AES_ERR_CHK
return aes_good;
#endif
}
#endif
#if defined(AES_VAR)
aes_rval aes_encrypt_key(const void *in_key, int key_len, aes_encrypt_ctx cx[1])
{
switch(key_len)
{
#ifdef AES_ERR_CHK
case 16: case 128: return aes_encrypt_key128(in_key, cx);
case 24: case 192: return aes_encrypt_key192(in_key, cx);
case 32: case 256: return aes_encrypt_key256(in_key, cx);
default: return aes_error;
#else
case 16: case 128: aes_encrypt_key128(in_key, cx); return;
case 24: case 192: aes_encrypt_key192(in_key, cx); return;
case 32: case 256: aes_encrypt_key256(in_key, cx); return;
#endif
}
}
#endif
#endif
#if defined(DECRYPTION_KEY_SCHEDULE)
#if DEC_ROUND == NO_TABLES
#define ff(x) (x)
#else
#define ff(x) inv_mcol(x)
#ifdef dec_imvars
#define d_vars dec_imvars
#endif
#endif
#if 1
#define kdf4(k,i) \
{ ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; ss[1] = ss[1] ^ ss[3]; ss[2] = ss[2] ^ ss[3]; ss[3] = ss[3]; \
ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \
ss[4] ^= k[4*(i)]; k[4*(i)+4] = ff(ss[4]); ss[4] ^= k[4*(i)+1]; k[4*(i)+5] = ff(ss[4]); \
ss[4] ^= k[4*(i)+2]; k[4*(i)+6] = ff(ss[4]); ss[4] ^= k[4*(i)+3]; k[4*(i)+7] = ff(ss[4]); \
}
#define kd4(k,i) \
{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \
k[4*(i)+4] = ss[4] ^= k[4*(i)]; k[4*(i)+5] = ss[4] ^= k[4*(i)+1]; \
k[4*(i)+6] = ss[4] ^= k[4*(i)+2]; k[4*(i)+7] = ss[4] ^= k[4*(i)+3]; \
}
#define kdl4(k,i) \
{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \
k[4*(i)+4] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; k[4*(i)+5] = ss[1] ^ ss[3]; \
k[4*(i)+6] = ss[0]; k[4*(i)+7] = ss[1]; \
}
#else
#define kdf4(k,i) \
{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+ 4] = ff(ss[0]); ss[1] ^= ss[0]; k[4*(i)+ 5] = ff(ss[1]); \
ss[2] ^= ss[1]; k[4*(i)+ 6] = ff(ss[2]); ss[3] ^= ss[2]; k[4*(i)+ 7] = ff(ss[3]); \
}
#define kd4(k,i) \
{ ss[4] = ls_box(ss[3],3) ^ t_use(r,c)[i]; \
ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[4*(i)+ 4] = ss[4] ^= k[4*(i)]; \
ss[1] ^= ss[0]; k[4*(i)+ 5] = ss[4] ^= k[4*(i)+ 1]; \
ss[2] ^= ss[1]; k[4*(i)+ 6] = ss[4] ^= k[4*(i)+ 2]; \
ss[3] ^= ss[2]; k[4*(i)+ 7] = ss[4] ^= k[4*(i)+ 3]; \
}
#define kdl4(k,i) \
{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+ 4] = ss[0]; ss[1] ^= ss[0]; k[4*(i)+ 5] = ss[1]; \
ss[2] ^= ss[1]; k[4*(i)+ 6] = ss[2]; ss[3] ^= ss[2]; k[4*(i)+ 7] = ss[3]; \
}
#endif
#define kdf6(k,i) \
{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 6] = ff(ss[0]); ss[1] ^= ss[0]; k[6*(i)+ 7] = ff(ss[1]); \
ss[2] ^= ss[1]; k[6*(i)+ 8] = ff(ss[2]); ss[3] ^= ss[2]; k[6*(i)+ 9] = ff(ss[3]); \
ss[4] ^= ss[3]; k[6*(i)+10] = ff(ss[4]); ss[5] ^= ss[4]; k[6*(i)+11] = ff(ss[5]); \
}
#define kd6(k,i) \
{ ss[6] = ls_box(ss[5],3) ^ t_use(r,c)[i]; \
ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[6*(i)+ 6] = ss[6] ^= k[6*(i)]; \
ss[1] ^= ss[0]; k[6*(i)+ 7] = ss[6] ^= k[6*(i)+ 1]; \
ss[2] ^= ss[1]; k[6*(i)+ 8] = ss[6] ^= k[6*(i)+ 2]; \
ss[3] ^= ss[2]; k[6*(i)+ 9] = ss[6] ^= k[6*(i)+ 3]; \
ss[4] ^= ss[3]; k[6*(i)+10] = ss[6] ^= k[6*(i)+ 4]; \
ss[5] ^= ss[4]; k[6*(i)+11] = ss[6] ^= k[6*(i)+ 5]; \
}
#define kdl6(k,i) \
{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 6] = ss[0]; ss[1] ^= ss[0]; k[6*(i)+ 7] = ss[1]; \
ss[2] ^= ss[1]; k[6*(i)+ 8] = ss[2]; ss[3] ^= ss[2]; k[6*(i)+ 9] = ss[3]; \
}
#define kdf8(k,i) \
{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 8] = ff(ss[0]); ss[1] ^= ss[0]; k[8*(i)+ 9] = ff(ss[1]); \
ss[2] ^= ss[1]; k[8*(i)+10] = ff(ss[2]); ss[3] ^= ss[2]; k[8*(i)+11] = ff(ss[3]); \
ss[4] ^= ls_box(ss[3],0); k[8*(i)+12] = ff(ss[4]); ss[5] ^= ss[4]; k[8*(i)+13] = ff(ss[5]); \
ss[6] ^= ss[5]; k[8*(i)+14] = ff(ss[6]); ss[7] ^= ss[6]; k[8*(i)+15] = ff(ss[7]); \
}
#define kd8(k,i) \
{ aes_32t g = ls_box(ss[7],3) ^ t_use(r,c)[i]; \
ss[0] ^= g; g = ff(g); k[8*(i)+ 8] = g ^= k[8*(i)]; \
ss[1] ^= ss[0]; k[8*(i)+ 9] = g ^= k[8*(i)+ 1]; \
ss[2] ^= ss[1]; k[8*(i)+10] = g ^= k[8*(i)+ 2]; \
ss[3] ^= ss[2]; k[8*(i)+11] = g ^= k[8*(i)+ 3]; \
g = ls_box(ss[3],0); \
ss[4] ^= g; g = ff(g); k[8*(i)+12] = g ^= k[8*(i)+ 4]; \
ss[5] ^= ss[4]; k[8*(i)+13] = g ^= k[8*(i)+ 5]; \
ss[6] ^= ss[5]; k[8*(i)+14] = g ^= k[8*(i)+ 6]; \
ss[7] ^= ss[6]; k[8*(i)+15] = g ^= k[8*(i)+ 7]; \
}
#define kdl8(k,i) \
{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 8] = ss[0]; ss[1] ^= ss[0]; k[8*(i)+ 9] = ss[1]; \
ss[2] ^= ss[1]; k[8*(i)+10] = ss[2]; ss[3] ^= ss[2]; k[8*(i)+11] = ss[3]; \
}
#if defined(AES_128) || defined(AES_VAR)
aes_rval aes_decrypt_key128(const void *in_key, aes_decrypt_ctx cx[1])
{ aes_32t ss[5];
#ifdef d_vars
d_vars;
#endif
cx->ks[0] = ss[0] = word_in(in_key, 0);
cx->ks[1] = ss[1] = word_in(in_key, 1);
cx->ks[2] = ss[2] = word_in(in_key, 2);
cx->ks[3] = ss[3] = word_in(in_key, 3);
#if DEC_UNROLL == NONE
{ aes_32t i;
for(i = 0; i < (11 * N_COLS - 1) / 4; ++i)
ke4(cx->ks, i);
#if !(DEC_ROUND == NO_TABLES)
for(i = N_COLS; i < 10 * N_COLS; ++i)
cx->ks[i] = inv_mcol(cx->ks[i]);
#endif
}
#else
kdf4(cx->ks, 0); kd4(cx->ks, 1);
kd4(cx->ks, 2); kd4(cx->ks, 3);
kd4(cx->ks, 4); kd4(cx->ks, 5);
kd4(cx->ks, 6); kd4(cx->ks, 7);
kd4(cx->ks, 8); kdl4(cx->ks, 9);
#endif
/* cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] is zero for a 256 bit */
/* key and must be non-zero for 128 and 192 bits keys */
cx->ks[53] = cx->ks[45] = 0;
cx->ks[52] = 10;
#ifdef AES_ERR_CHK
return aes_good;
#endif
}
#endif
#if defined(AES_192) || defined(AES_VAR)
aes_rval aes_decrypt_key192(const void *in_key, aes_decrypt_ctx cx[1])
{ aes_32t ss[7];
#ifdef d_vars
d_vars;
#endif
cx->ks[0] = ss[0] = word_in(in_key, 0);
cx->ks[1] = ss[1] = word_in(in_key, 1);
cx->ks[2] = ss[2] = word_in(in_key, 2);
cx->ks[3] = ss[3] = word_in(in_key, 3);
#if DEC_UNROLL == NONE
cx->ks[4] = ss[4] = word_in(in_key, 4);
cx->ks[5] = ss[5] = word_in(in_key, 5);
{ aes_32t i;
for(i = 0; i < (13 * N_COLS - 1) / 6; ++i)
ke6(cx->ks, i);
#if !(DEC_ROUND == NO_TABLES)
for(i = N_COLS; i < 12 * N_COLS; ++i)
cx->ks[i] = inv_mcol(cx->ks[i]);
#endif
}
#else
cx->ks[4] = ff(ss[4] = word_in(in_key, 4));
cx->ks[5] = ff(ss[5] = word_in(in_key, 5));
kdf6(cx->ks, 0); kd6(cx->ks, 1);
kd6(cx->ks, 2); kd6(cx->ks, 3);
kd6(cx->ks, 4); kd6(cx->ks, 5);
kd6(cx->ks, 6); kdl6(cx->ks, 7);
#endif
/* cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] is zero for a 256 bit */
/* key and must be non-zero for 128 and 192 bits keys */
cx->ks[53] = cx->ks[45];
cx->ks[52] = 12;
#ifdef AES_ERR_CHK
return aes_good;
#endif
}
#endif
#if defined(AES_256) || defined(AES_VAR)
aes_rval aes_decrypt_key256(const void *in_key, aes_decrypt_ctx cx[1])
{ aes_32t ss[8];
#ifdef d_vars
d_vars;
#endif
cx->ks[0] = ss[0] = word_in(in_key, 0);
cx->ks[1] = ss[1] = word_in(in_key, 1);
cx->ks[2] = ss[2] = word_in(in_key, 2);
cx->ks[3] = ss[3] = word_in(in_key, 3);
#if DEC_UNROLL == NONE
cx->ks[4] = ss[4] = word_in(in_key, 4);
cx->ks[5] = ss[5] = word_in(in_key, 5);
cx->ks[6] = ss[6] = word_in(in_key, 6);
cx->ks[7] = ss[7] = word_in(in_key, 7);
{ aes_32t i;
for(i = 0; i < (15 * N_COLS - 1) / 8; ++i)
ke8(cx->ks, i);
#if !(DEC_ROUND == NO_TABLES)
for(i = N_COLS; i < 14 * N_COLS; ++i)
cx->ks[i] = inv_mcol(cx->ks[i]);
#endif
}
#else
cx->ks[4] = ff(ss[4] = word_in(in_key, 4));
cx->ks[5] = ff(ss[5] = word_in(in_key, 5));
cx->ks[6] = ff(ss[6] = word_in(in_key, 6));
cx->ks[7] = ff(ss[7] = word_in(in_key, 7));
kdf8(cx->ks, 0); kd8(cx->ks, 1);
kd8(cx->ks, 2); kd8(cx->ks, 3);
kd8(cx->ks, 4); kd8(cx->ks, 5);
kdl8(cx->ks, 6);
#endif
#ifdef AES_ERR_CHK
return aes_good;
#endif
}
#endif
#if defined(AES_VAR)
aes_rval aes_decrypt_key(const void *in_key, int key_len, aes_decrypt_ctx cx[1])
{
switch(key_len)
{
#ifdef AES_ERR_CHK
case 16: case 128: return aes_decrypt_key128(in_key, cx);
case 24: case 192: return aes_decrypt_key192(in_key, cx);
case 32: case 256: return aes_decrypt_key256(in_key, cx);
default: return aes_error;
#else
case 16: case 128: aes_decrypt_key128(in_key, cx); return;
case 24: case 192: aes_decrypt_key192(in_key, cx); return;
case 32: case 256: aes_decrypt_key256(in_key, cx); return;
#endif
}
}
#endif
#endif
#if defined(__cplusplus)
}
#endif

1041
aesopt.h

File diff suppressed because it is too large Load Diff

232
aestab.c
View File

@@ -1,232 +0,0 @@
/*
---------------------------------------------------------------------------
Copyright (c) 2003, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 26/08/2003
*/
#if defined(__cplusplus)
extern "C"
{
#endif
#define DO_TABLES
#include "aesopt.h"
#if defined(FIXED_TABLES)
/* implemented in case of wrong call for fixed tables */
void gen_tabs(void)
{
}
#else /* dynamic table generation */
#if !defined(FF_TABLES)
/* Generate the tables for the dynamic table option
It will generally be sensible to use tables to compute finite
field multiplies and inverses but where memory is scarse this
code might sometimes be better. But it only has effect during
initialisation so its pretty unimportant in overall terms.
*/
/* return 2 ^ (n - 1) where n is the bit number of the highest bit
set in x with x in the range 1 < x < 0x00000200. This form is
used so that locals within fi can be bytes rather than words
*/
static aes_08t hibit(const aes_32t x)
{ aes_08t r = (aes_08t)((x >> 1) | (x >> 2));
r |= (r >> 2);
r |= (r >> 4);
return (r + 1) >> 1;
}
/* return the inverse of the finite field element x */
static aes_08t fi(const aes_08t x)
{ aes_08t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;
if(x < 2) return x;
for(;;)
{
if(!n1) return v1;
while(n2 >= n1)
{
n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2);
}
if(!n2) return v2;
while(n1 >= n2)
{
n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1);
}
}
}
#endif
/* The forward and inverse affine transformations used in the S-box */
#define fwd_affine(x) \
(w = (aes_32t)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(aes_08t)(w^(w>>8)))
#define inv_affine(x) \
(w = (aes_32t)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(aes_08t)(w^(w>>8)))
static int init = 0;
void gen_tabs(void)
{ aes_32t i, w;
#if defined(FF_TABLES)
aes_08t pow[512], log[256];
if(init) return;
/* log and power tables for GF(2^8) finite field with
WPOLY as modular polynomial - the simplest primitive
root is 0x03, used here to generate the tables
*/
i = 0; w = 1;
do
{
pow[i] = (aes_08t)w;
pow[i + 255] = (aes_08t)w;
log[w] = (aes_08t)i++;
w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0);
}
while (w != 1);
#else
if(init) return;
#endif
for(i = 0, w = 1; i < RC_LENGTH; ++i)
{
t_set(r,c)[i] = bytes2word(w, 0, 0, 0);
w = f2(w);
}
for(i = 0; i < 256; ++i)
{ aes_08t b;
b = fwd_affine(fi((aes_08t)i));
w = bytes2word(f2(b), b, b, f3(b));
#ifdef SBX_SET
t_set(s,box)[i] = b;
#endif
#ifdef FT1_SET /* tables for a normal encryption round */
t_set(f,n)[i] = w;
#endif
#ifdef FT4_SET
t_set(f,n)[0][i] = w;
t_set(f,n)[1][i] = upr(w,1);
t_set(f,n)[2][i] = upr(w,2);
t_set(f,n)[3][i] = upr(w,3);
#endif
w = bytes2word(b, 0, 0, 0);
#ifdef FL1_SET /* tables for last encryption round (may also */
t_set(f,l)[i] = w; /* be used in the key schedule) */
#endif
#ifdef FL4_SET
t_set(f,l)[0][i] = w;
t_set(f,l)[1][i] = upr(w,1);
t_set(f,l)[2][i] = upr(w,2);
t_set(f,l)[3][i] = upr(w,3);
#endif
#ifdef LS1_SET /* table for key schedule if t_set(f,l) above is */
t_set(l,s)[i] = w; /* not of the required form */
#endif
#ifdef LS4_SET
t_set(l,s)[0][i] = w;
t_set(l,s)[1][i] = upr(w,1);
t_set(l,s)[2][i] = upr(w,2);
t_set(l,s)[3][i] = upr(w,3);
#endif
b = fi(inv_affine((aes_08t)i));
w = bytes2word(fe(b), f9(b), fd(b), fb(b));
#ifdef IM1_SET /* tables for the inverse mix column operation */
t_set(i,m)[b] = w;
#endif
#ifdef IM4_SET
t_set(i,m)[0][b] = w;
t_set(i,m)[1][b] = upr(w,1);
t_set(i,m)[2][b] = upr(w,2);
t_set(i,m)[3][b] = upr(w,3);
#endif
#ifdef ISB_SET
t_set(i,box)[i] = b;
#endif
#ifdef IT1_SET /* tables for a normal decryption round */
t_set(i,n)[i] = w;
#endif
#ifdef IT4_SET
t_set(i,n)[0][i] = w;
t_set(i,n)[1][i] = upr(w,1);
t_set(i,n)[2][i] = upr(w,2);
t_set(i,n)[3][i] = upr(w,3);
#endif
w = bytes2word(b, 0, 0, 0);
#ifdef IL1_SET /* tables for last decryption round */
t_set(i,l)[i] = w;
#endif
#ifdef IL4_SET
t_set(i,l)[0][i] = w;
t_set(i,l)[1][i] = upr(w,1);
t_set(i,l)[2][i] = upr(w,2);
t_set(i,l)[3][i] = upr(w,3);
#endif
}
init = 1;
}
#endif
#if defined(__cplusplus)
}
#endif

View File

@@ -1,82 +0,0 @@
#!/usr/bin/perl
#
# Simple AGI application to play mp3's selected by a user both using
# xmms and over the phone itself.
#
$|=1;
while(<STDIN>) {
chomp;
last unless length($_);
if (/^agi_(\w+)\:\s+(.*)$/) {
$AGI{$1} = $2;
}
}
print STDERR "AGI Environment Dump:\n";
foreach $i (sort keys %AGI) {
print STDERR " -- $i = $AGI{$i}\n";
}
dbmopen(%DIGITS, "/var/lib/asterisk/mp3list", 0644) || die("Unable to open mp3list");;
sub checkresult {
my ($res) = @_;
my $retval;
$tests++;
chomp $res;
if ($res =~ /^200/) {
$res =~ /result=(-?[\w\*\#]+)/;
return $1;
} else {
return -1;
}
}
#print STDERR "1. Playing beep...\n";
#print "STREAM FILE beep \"\"\n";
#$result = <STDIN>;
#checkresult($result);
print STDERR "2. Getting song name...\n";
print "GET DATA demo-enterkeywords\n";
$result = <STDIN>;
$digitstr = checkresult($result);
if ($digitstr < 0) {
exit(1);
}
$digitstr =~ s/\*/ /g;
print STDERR "Resulting songname is $digitstr\n";
@searchwords = split (/\s+/, $digitstr);
print STDERR "Searchwords: " . join(':', @searchwords) . "\n";
foreach $key (sort keys %DIGITS) {
@words = split(/\s+/, $DIGITS{$key});
$match = 1;
foreach $search (@searchwords) {
$match = 0 unless grep(/$search/, @words);
}
if ($match > 0) {
print STDERR "File $key matches\n";
# Play a beep
print "STREAM FILE beep \"\"\n";
system("xmms", $key);
$result = <STDIN>;
if (&checkresult($result) < 0) {
exit 0;
}
print "EXEC MP3Player \"$key\"\n";
# print "WAIT FOR DIGIT 60000\n";
$result = <STDIN>;
if (&checkresult($result) < 0) {
exit 0;
}
print STDERR "Got here...\n";
}
}
print STDERR "4. Testing 'saynumber' of $digitstr...\n";
print "STREAM FILE demo-nomatch\"\"\n";
$result = <STDIN>;
checkresult($result);

View File

@@ -11,33 +11,17 @@
# the GNU General Public License
#
AGIS=agi-test.agi eagi-test eagi-sphinx-test
AGIS=agi-test.agi
CFLAGS+=
all: depend $(AGIS)
all: $(AGIS)
install: all
mkdir -p $(DESTDIR)$(AGI_DIR)
for x in $(AGIS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(AGI_DIR) ; done
eagi-test: eagi-test.o
$(CC) -o eagi-test eagi-test.o
eagi-sphinx-test: eagi-sphinx-test.o
$(CC) -o eagi-sphinx-test eagi-sphinx-test.o
for x in $(AGIS); do $(INSTALL) -m 755 $$x $(AGI_DIR) ; done
clean:
rm -f *.so *.o look .depend
rm -f *.so *.o look
%.so : %.o
$(CC) -shared -Xlinker -x -o $@ $<
ifneq ($(wildcard .depend),)
include .depend
endif
depend: .depend
.depend:
../mkdep $(CFLAGS) `ls *.c`

View File

@@ -1,11 +1,5 @@
#!/usr/bin/perl
use strict;
$|=1;
# Setup some variables
my %AGI; my $tests = 0; my $fail = 0; my $pass = 0;
while(<STDIN>) {
chomp;
last unless length($_);
@@ -15,7 +9,7 @@ while(<STDIN>) {
}
print STDERR "AGI Environment Dump:\n";
foreach my $i (sort keys %AGI) {
foreach $i (sort keys %AGI) {
print STDERR " -- $i = $AGI{$i}\n";
}
@@ -41,38 +35,38 @@ sub checkresult {
print STDERR "1. Testing 'sendfile'...";
print "STREAM FILE beep \"\"\n";
my $result = <STDIN>;
&checkresult($result);
$result = <STDIN>;
checkresult($result);
print STDERR "2. Testing 'sendtext'...";
print "SEND TEXT \"hello world\"\n";
my $result = <STDIN>;
&checkresult($result);
$result = <STDIN>;
checkresult($result);
print STDERR "3. Testing 'sendimage'...";
print "SEND IMAGE asterisk-image\n";
my $result = <STDIN>;
&checkresult($result);
$result = <STDIN>;
checkresult($result);
print STDERR "4. Testing 'saynumber'...";
print "SAY NUMBER 192837465 \"\"\n";
my $result = <STDIN>;
&checkresult($result);
$result = <STDIN>;
checkresult($result);
print STDERR "5. Testing 'waitdtmf'...";
print "WAIT FOR DIGIT 1000\n";
my $result = <STDIN>;
&checkresult($result);
$result = <STDIN>;
checkresult($result);
print STDERR "6. Testing 'record'...";
print "RECORD FILE testagi gsm 1234 3000\n";
my $result = <STDIN>;
&checkresult($result);
$result = <STDIN>;
checkresult($result);
print STDERR "6a. Testing 'record' playback...";
print "STREAM FILE testagi \"\"\n";
my $result = <STDIN>;
&checkresult($result);
$result = <STDIN>;
checkresult($result);
print STDERR "================== Complete ======================\n";
print STDERR "$tests tests completed, $pass passed, $fail failed\n";

View File

@@ -1,218 +0,0 @@
/*
* Extended AGI test application
*
* This code is released into public domain
* without any warranty of any kind.
*
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/select.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define AUDIO_FILENO (STDERR_FILENO + 1)
#define SPHINX_HOST "192.168.1.108"
#define SPHINX_PORT 3460
static int sphinx_sock = -1;
static int connect_sphinx(void)
{
struct hostent *hp;
struct sockaddr_in sin;
int res;
hp = gethostbyname(SPHINX_HOST);
if (!hp) {
fprintf(stderr, "Unable to resolve '%s'\n", SPHINX_HOST);
return -1;
}
sphinx_sock = socket(PF_INET, SOCK_STREAM, 0);
if (sphinx_sock < 0) {
fprintf(stderr, "Unable to allocate socket: %s\n", strerror(errno));
return -1;
}
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(SPHINX_PORT);
memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
if (connect(sphinx_sock, (struct sockaddr *)&sin, sizeof(sin))) {
fprintf(stderr, "Unable to connect on socket: %s\n", strerror(errno));
close(sphinx_sock);
sphinx_sock = -1;
return -1;
}
res = fcntl(sphinx_sock, F_GETFL);
if ((res < 0) || (fcntl(sphinx_sock, F_SETFL, res | O_NONBLOCK) < 0)) {
fprintf(stderr, "Unable to set flags on socket: %s\n", strerror(errno));
close(sphinx_sock);
sphinx_sock = -1;
return -1;
}
return 0;
}
static int read_environment(void)
{
char buf[256];
char *val;
/* Read environment */
for(;;) {
fgets(buf, sizeof(buf), stdin);
if (feof(stdin))
return -1;
buf[strlen(buf) - 1] = '\0';
/* Check for end of environment */
if (!strlen(buf))
return 0;
val = strchr(buf, ':');
if (!val) {
fprintf(stderr, "Invalid environment: '%s'\n", buf);
return -1;
}
*val = '\0';
val++;
val++;
/* Skip space */
fprintf(stderr, "Environment: '%s' is '%s'\n", buf, val);
/* Load into normal environment */
setenv(buf, val, 1);
}
/* Never reached */
return 0;
}
static char *wait_result(void)
{
fd_set fds;
int res;
int max;
static char astresp[256];
static char sphinxresp[256];
char audiobuf[4096];
for (;;) {
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
FD_SET(AUDIO_FILENO, &fds);
max = AUDIO_FILENO;
if (sphinx_sock > -1) {
FD_SET(sphinx_sock, &fds);
if (sphinx_sock > max)
max = sphinx_sock;
}
/* Wait for *some* sort of I/O */
res = select(max + 1, &fds, NULL, NULL, NULL);
if (res < 0) {
fprintf(stderr, "Error in select: %s\n", strerror(errno));
return NULL;
}
if (FD_ISSET(STDIN_FILENO, &fds)) {
fgets(astresp, sizeof(astresp), stdin);
if (feof(stdin)) {
fprintf(stderr, "Got hungup on apparently\n");
return NULL;
}
astresp[strlen(astresp) - 1] = '\0';
fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp);
return astresp;
}
if (FD_ISSET(AUDIO_FILENO, &fds)) {
res = read(AUDIO_FILENO, audiobuf, sizeof(audiobuf));
if (res > 0) {
if (sphinx_sock > -1)
write(sphinx_sock, audiobuf, res);
}
}
if ((sphinx_sock > -1) && FD_ISSET(sphinx_sock, &fds)) {
res = read(sphinx_sock, sphinxresp, sizeof(sphinxresp));
if (res > 0) {
fprintf(stderr, "Oooh, Sphinx found a token: '%s'\n", sphinxresp);
return sphinxresp;
} else if (res == 0) {
fprintf(stderr, "Hrm, lost sphinx, guess we're on our own\n");
close(sphinx_sock);
sphinx_sock = -1;
}
}
}
}
static char *run_command(char *command)
{
fprintf(stdout, "%s\n", command);
return wait_result();
}
static int run_script(void)
{
char *res;
res = run_command("STREAM FILE demo-enterkeywords 0123456789*#");
if (!res) {
fprintf(stderr, "Failed to execute command\n");
return -1;
}
fprintf(stderr, "1. Result is '%s'\n", res);
res = run_command("STREAM FILE demo-nomatch 0123456789*#");
if (!res) {
fprintf(stderr, "Failed to execute command\n");
return -1;
}
fprintf(stderr, "2. Result is '%s'\n", res);
res = run_command("SAY NUMBER 23452345 0123456789*#");
if (!res) {
fprintf(stderr, "Failed to execute command\n");
return -1;
}
fprintf(stderr, "3. Result is '%s'\n", res);
res = run_command("GET DATA demo-enterkeywords");
if (!res) {
fprintf(stderr, "Failed to execute command\n");
return -1;
}
fprintf(stderr, "4. Result is '%s'\n", res);
res = run_command("STREAM FILE auth-thankyou \"\"");
if (!res) {
fprintf(stderr, "Failed to execute command\n");
return -1;
}
fprintf(stderr, "5. Result is '%s'\n", res);
return 0;
}
int main(int argc, char *argv[])
{
char *tmp;
int ver = 0;
int subver = 0;
/* Setup stdin/stdout for line buffering */
setlinebuf(stdin);
setlinebuf(stdout);
if (read_environment()) {
fprintf(stderr, "Failed to read environment: %s\n", strerror(errno));
exit(1);
}
connect_sphinx();
tmp = getenv("agi_enhanced");
if (tmp) {
if (sscanf(tmp, "%d.%d", &ver, &subver) != 2)
ver = 0;
}
if (ver < 1) {
fprintf(stderr, "No enhanced AGI services available. Use EAGI, not AGI\n");
exit(1);
}
if (run_script())
return -1;
exit(0);
}

View File

@@ -1,161 +0,0 @@
/*
* Extended AGI test application
*
* This code is released into the public domain
* with no warranty of any kind
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/select.h>
#define AUDIO_FILENO (STDERR_FILENO + 1)
static int read_environment(void)
{
char buf[256];
char *val;
/* Read environment */
for(;;) {
fgets(buf, sizeof(buf), stdin);
if (feof(stdin))
return -1;
buf[strlen(buf) - 1] = '\0';
/* Check for end of environment */
if (!strlen(buf))
return 0;
val = strchr(buf, ':');
if (!val) {
fprintf(stderr, "Invalid environment: '%s'\n", buf);
return -1;
}
*val = '\0';
val++;
val++;
/* Skip space */
fprintf(stderr, "Environment: '%s' is '%s'\n", buf, val);
/* Load into normal environment */
setenv(buf, val, 1);
}
/* Never reached */
return 0;
}
static char *wait_result(void)
{
fd_set fds;
int res;
int bytes = 0;
static char astresp[256];
char audiobuf[4096];
for (;;) {
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
FD_SET(AUDIO_FILENO, &fds);
/* Wait for *some* sort of I/O */
res = select(AUDIO_FILENO + 1, &fds, NULL, NULL, NULL);
if (res < 0) {
fprintf(stderr, "Error in select: %s\n", strerror(errno));
return NULL;
}
if (FD_ISSET(STDIN_FILENO, &fds)) {
fgets(astresp, sizeof(astresp), stdin);
if (feof(stdin)) {
fprintf(stderr, "Got hungup on apparently\n");
return NULL;
}
astresp[strlen(astresp) - 1] = '\0';
fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp);
return astresp;
}
if (FD_ISSET(AUDIO_FILENO, &fds)) {
res = read(AUDIO_FILENO, audiobuf, sizeof(audiobuf));
if (res > 0) {
/* XXX Process the audio with sphinx here XXX */
#if 0
fprintf(stderr, "Got %d/%d bytes of audio\n", res, bytes);
#endif
bytes += res;
/* Prentend we detected some audio after 3 seconds */
if (bytes > 16000 * 3) {
return "Sample Message";
bytes = 0;
}
}
}
}
}
static char *run_command(char *command)
{
fprintf(stdout, "%s\n", command);
return wait_result();
}
static int run_script(void)
{
char *res;
res = run_command("STREAM FILE demo-enterkeywords 0123456789*#");
if (!res) {
fprintf(stderr, "Failed to execute command\n");
return -1;
}
fprintf(stderr, "1. Result is '%s'\n", res);
res = run_command("STREAM FILE demo-nomatch 0123456789*#");
if (!res) {
fprintf(stderr, "Failed to execute command\n");
return -1;
}
fprintf(stderr, "2. Result is '%s'\n", res);
res = run_command("SAY NUMBER 23452345 0123456789*#");
if (!res) {
fprintf(stderr, "Failed to execute command\n");
return -1;
}
fprintf(stderr, "3. Result is '%s'\n", res);
res = run_command("GET DATA demo-enterkeywords");
if (!res) {
fprintf(stderr, "Failed to execute command\n");
return -1;
}
fprintf(stderr, "4. Result is '%s'\n", res);
res = run_command("STREAM FILE auth-thankyou \"\"");
if (!res) {
fprintf(stderr, "Failed to execute command\n");
return -1;
}
fprintf(stderr, "5. Result is '%s'\n", res);
return 0;
}
int main(int argc, char *argv[])
{
char *tmp;
int ver = 0;
int subver = 0;
/* Setup stdin/stdout for line buffering */
setlinebuf(stdin);
setlinebuf(stdout);
if (read_environment()) {
fprintf(stderr, "Failed to read environment: %s\n", strerror(errno));
exit(1);
}
tmp = getenv("agi_enhanced");
if (tmp) {
if (sscanf(tmp, "%d.%d", &ver, &subver) != 2)
ver = 0;
}
if (ver < 1) {
fprintf(stderr, "No enhanced AGI services available. Use EAGI, not AGI\n");
exit(1);
}
if (run_script())
return -1;
exit(0);
}

View File

@@ -1,44 +0,0 @@
#!/usr/bin/perl
#
# Build a database linking filenames to their numerical representations
# using a keypad for the DialAnMp3 application
#
$mp3dir="/usr/media/mpeg3";
dbmopen(%DIGITS, "/var/lib/asterisk/mp3list", 0644) || die("Unable to open mp3list");;
sub process_dir {
my ($dir) = @_;
my $file;
my $digits;
my @entries;
opendir(DIR, $dir);
@entries = readdir(DIR);
closedir(DIR);
foreach $_ (@entries) {
if (!/^\./) {
$file = "$dir/$_";
if (-d "$file") {
process_dir("$file");
} else {
$digits = $_;
$digits =~ s/[^ \w]+//g;
$digits =~ s/\_/ /g;
$digits =~ tr/[a-z]/[A-Z]/;
$digits =~ tr/[A-C]/2/;
$digits =~ tr/[D-F]/3/;
$digits =~ tr/[G-I]/4/;
$digits =~ tr/[J-L]/5/;
$digits =~ tr/[M-O]/6/;
$digits =~ tr/[P-S]/7/;
$digits =~ tr/[T-V]/8/;
$digits =~ tr/[W-Z]/9/;
$digits =~ s/\s+/ /;
print "File: $file, digits: $digits\n";
$DIGITS{$file} = $digits;
}
}
}
}
process_dir($mp3dir);

85
alaw.c
View File

@@ -1,85 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* u-Law to Signed linear conversion
*
* 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/alaw.h>
#define AMI_MASK 0x55
static inline unsigned char linear2alaw (short int linear)
{
int mask;
int seg;
int pcm_val;
static int seg_end[8] =
{
0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF
};
pcm_val = linear;
if (pcm_val >= 0)
{
/* Sign (7th) bit = 1 */
mask = AMI_MASK | 0x80;
}
else
{
/* Sign bit = 0 */
mask = AMI_MASK;
pcm_val = -pcm_val;
}
/* Convert the scaled magnitude to segment number. */
for (seg = 0; seg < 8; seg++)
{
if (pcm_val <= seg_end[seg])
break;
}
/* Combine the sign, segment, and quantization bits. */
return ((seg << 4) | ((pcm_val >> ((seg) ? (seg + 3) : 4)) & 0x0F)) ^ mask;
}
/*- End of function --------------------------------------------------------*/
static inline short int alaw2linear (unsigned char alaw)
{
int i;
int seg;
alaw ^= AMI_MASK;
i = ((alaw & 0x0F) << 4);
seg = (((int) alaw & 0x70) >> 4);
if (seg)
i = (i + 0x100) << (seg - 1);
return (short int) ((alaw & 0x80) ? i : -i);
}
unsigned char __ast_lin2a[8192];
short __ast_alaw[256];
void ast_alaw_init(void)
{
int i;
/*
* Set up mu-law conversion table
*/
for(i = 0;i < 256;i++)
{
__ast_alaw[i] = alaw2linear(i);
}
/* set up the reverse (mu-law) conversion table */
for(i = -32768; i < 32768; i++)
{
__ast_lin2a[((unsigned short)i) >> 3] = linear2alaw(i);
}
}

219
app.c
View File

@@ -19,39 +19,13 @@
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <dirent.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/file.h>
#include <asterisk/app.h>
#include <asterisk/dsp.h>
#include <asterisk/logger.h>
#include <asterisk/options.h>
#include "asterisk.h"
#include "astconf.h"
/* 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 (prompt) {
res = ast_streamfile(c, prompt, c->language);
if (res < 0)
return res;
}
fto = c->pbx ? c->pbx->rtimeout * 1000 : 6000;
to = c->pbx ? c->pbx->dtimeout * 1000 : 2000;
if (timeout > 0) fto = to = timeout;
if (timeout < 0) fto = to = 1000000000;
res = ast_readstring(c, s, maxlen, to, fto, "#");
return res;
}
int ast_app_getdata_full(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd)
{
int res,to,fto;
if (prompt) {
@@ -63,198 +37,7 @@ int ast_app_getdata_full(struct ast_channel *c, char *prompt, char *s, int maxle
to = 2000;
if (timeout > 0) fto = to = timeout;
if (timeout < 0) fto = to = 1000000000;
res = ast_readstring_full(c, s, maxlen, to, fto, "#", audiofd, ctrlfd);
res = ast_readstring(c, s, maxlen, to, fto, "#");
return res;
}
int ast_app_getvoice(struct ast_channel *c, char *dest, char *dstfmt, char *prompt, int silence, int maxsec)
{
int res;
struct ast_filestream *writer;
int rfmt;
int totalms=0, total;
struct ast_frame *f;
struct ast_dsp *sildet;
/* Play prompt if requested */
if (prompt) {
res = ast_streamfile(c, prompt, c->language);
if (res < 0)
return res;
res = ast_waitstream(c,"");
if (res < 0)
return res;
}
rfmt = c->readformat;
res = ast_set_read_format(c, AST_FORMAT_SLINEAR);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
return -1;
}
sildet = ast_dsp_new();
if (!sildet) {
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
return -1;
}
writer = ast_writefile(dest, dstfmt, "Voice file", 0, 0, 0666);
if (!writer) {
ast_log(LOG_WARNING, "Unable to open file '%s' in format '%s' for writing\n", dest, dstfmt);
ast_dsp_free(sildet);
return -1;
}
for(;;) {
if ((res = ast_waitfor(c, 2000)) < 0) {
ast_log(LOG_NOTICE, "Waitfor failed while recording file '%s' format '%s'\n", dest, dstfmt);
break;
}
if (res) {
f = ast_read(c);
if (!f) {
ast_log(LOG_NOTICE, "Hungup while recording file '%s' format '%s'\n", dest, dstfmt);
break;
}
if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
/* Ended happily with DTMF */
ast_frfree(f);
break;
} else if (f->frametype == AST_FRAME_VOICE) {
ast_dsp_silence(sildet, f, &total);
if (total > silence) {
/* Ended happily with silence */
ast_frfree(f);
break;
}
totalms += f->samples / 8;
if (totalms > maxsec * 1000) {
/* Ended happily with too much stuff */
ast_log(LOG_NOTICE, "Constraining voice on '%s' to %d seconds\n", c->name, maxsec);
ast_frfree(f);
break;
}
}
ast_frfree(f);
}
}
res = ast_set_read_format(c, rfmt);
if (res)
ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", c->name);
ast_dsp_free(sildet);
ast_closestream(writer);
return 0;
}
int ast_app_has_voicemail(const char *mailbox)
{
DIR *dir;
struct dirent *de;
char fn[256];
char tmp[256]="";
char *mb, *cur;
char *context;
int ret;
/* If no mailbox, return immediately */
if (!strlen(mailbox))
return 0;
if (strchr(mailbox, ',')) {
strncpy(tmp, mailbox, sizeof(tmp));
mb = tmp;
ret = 0;
while((cur = strsep(&mb, ","))) {
if (strlen(cur)) {
if (ast_app_has_voicemail(cur))
return 1;
}
}
return 0;
}
strncpy(tmp, mailbox, sizeof(tmp) - 1);
context = strchr(tmp, '@');
if (context) {
*context = '\0';
context++;
} else
context = "default";
snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, context, tmp);
dir = opendir(fn);
if (!dir)
return 0;
while ((de = readdir(dir))) {
if (!strncasecmp(de->d_name, "msg", 3))
break;
}
closedir(dir);
if (de)
return 1;
return 0;
}
int ast_app_messagecount(const char *mailbox, int *newmsgs, int *oldmsgs)
{
DIR *dir;
struct dirent *de;
char fn[256];
char tmp[256]="";
char *mb, *cur;
char *context;
int ret;
if (newmsgs)
*newmsgs = 0;
if (oldmsgs)
*oldmsgs = 0;
/* If no mailbox, return immediately */
if (!strlen(mailbox))
return 0;
if (strchr(mailbox, ',')) {
int tmpnew, tmpold;
strncpy(tmp, mailbox, sizeof(tmp));
mb = tmp;
ret = 0;
while((cur = strsep(&mb, ", "))) {
if (strlen(cur)) {
if (ast_app_messagecount(cur, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
return -1;
else {
if (newmsgs)
*newmsgs += tmpnew;
if (oldmsgs)
*oldmsgs += tmpold;
}
}
}
return 0;
}
strncpy(tmp, mailbox, sizeof(tmp) - 1);
context = strchr(tmp, '@');
if (context) {
*context = '\0';
context++;
} else
context = "default";
if (newmsgs) {
snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, context, tmp);
dir = opendir(fn);
if (dir) {
while ((de = readdir(dir))) {
if ((strlen(de->d_name) > 3) && !strncasecmp(de->d_name, "msg", 3) &&
!strcasecmp(de->d_name + strlen(de->d_name) - 3, "txt"))
(*newmsgs)++;
}
closedir(dir);
}
}
if (oldmsgs) {
snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/Old", (char *)ast_config_AST_SPOOL_DIR, context, tmp);
dir = opendir(fn);
if (dir) {
while ((de = readdir(dir))) {
if ((strlen(de->d_name) > 3) && !strncasecmp(de->d_name, "msg", 3) &&
!strcasecmp(de->d_name + strlen(de->d_name) - 3, "txt"))
(*oldmsgs)++;
}
closedir(dir);
}
}
return 0;
}

View File

@@ -11,90 +11,29 @@
# the GNU General Public License
#
USE_MYSQL_VM_INTERFACE=0
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\
APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_intercom.so app_mp3.so \
app_system.so app_echo.so app_record.so app_image.so app_url.so app_disa.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_agi.so
ifneq (${OSARCH},Darwin)
APPS+=app_intercom.so
endif
#APPS+=app_sql_postgres.so
#APPS+=app_sql_odbc.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/include/zap.h ]; then echo "app_rpt.so" ; fi)
CFLAGS+=-fPIC
ifeq ($(USE_POSTGRES_VM_INTERFACE),1)
CFLAGS+=-DUSEPOSTGRESVM
endif
ifeq ($(USE_MYSQL_VM_INTERFACE),1)
CFLAGS+=-DUSEMYSQLVM
endif
CFLAGS+=
all: $(APPS)
clean:
rm -f *.so *.o look .depend
rm -f *.so *.o look
%.so : %.o
$(CC) $(SOLINK) -o $@ $<
app_rpt.so : app_rpt.o
$(CC) $(SOLINK) -o $@ $< -ltonezone
$(CC) -shared -Xlinker -x -o $@ $<
install: all
for x in $(APPS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
for x in $(APPS); do $(INSTALL) -m 755 $$x $(MODULES_DIR) ; done
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
gcc -pipe -O6 -g -Iinclude -I../include -D_REENTRANT -march=i586 -DDO_CRASH -DDEBUG_THREADS -c -o app_todd.o app_todd.c
app_todd.so: app_todd.o
$(CC) $(SOLINK) -o $@ $< -L/usr/local/ssl/lib -lssl -lcrypto
$(CC) -shared -Xlinker -x -o $@ $< -L/usr/local/ssl/lib -lssl -lcrypto
app_voicemail.so : app_voicemail.o
ifeq ($(USE_MYSQL_VM_INTERFACE),1)
$(CC) $(SOLINK) -o $@ $(MLFLAGS) $< -L/usr/lib/mysql -lmysqlclient -lz
else
ifeq ($(USE_POSTGRES_VM_INTERFACE),1)
$(CC) $(SOLINK) -o $@ $(MLFLAGS) $< -lpq
else
$(CC) $(SOLINK) -o $@ $(MLFLAGS) $<
endif
endif
app_sql_postgres.o: app_sql_postgres.c
$(CC) -pipe -I/usr/local/pgsql/include $(CFLAGS) -c -o app_sql_postgres.o app_sql_postgres.c
app_sql_postgres.so: app_sql_postgres.o
$(CC) $(SOLINK) -o $@ $< -L/usr/local/pgsql/lib -lpq
app_sql_odbc.so: app_sql_odbc.o
$(CC) $(SOLINK) -o $@ $< -lodbc
look: look.c
gcc -pipe -O6 -g look.c -o look -lncurses
ifneq ($(wildcard .depend),)
include .depend
endif
depend: .depend
.depend:
../mkdep $(CFLAGS) `ls *.c`

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,156 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Execute arbitrary authenticate commands
*
* 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/module.h>
#include <asterisk/app.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";
static char *app = "Authenticate";
static char *synopsis = "Authenticate a user";
static char *descrip =
" Authenticate(password[|options]): Requires a user to enter a"
"given password in order to continue execution. If the\n"
"password begins with the '/' character, it is interpreted as\n"
"a file which contains a list of valid passwords (1 per line).\n"
"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"
"\n"
"Returns 0 if the user enters a valid password within three\n"
"tries, or -1 otherwise (or on hangup).\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int auth_exec(struct ast_channel *chan, void *data)
{
int res=0;
int retries;
struct localuser *u;
char password[256]="";
char passwd[256];
char *opts;
char *prompt;
if (!data || !strlen(data)) {
ast_log(LOG_WARNING, "Authenticate requires an argument(password)\n");
return -1;
}
LOCAL_USER_ADD(u);
if (chan->_state != AST_STATE_UP) {
res = ast_answer(chan);
if (res) {
LOCAL_USER_REMOVE(u);
return -1;
}
}
strncpy(password, data, sizeof(password) - 1);
opts=strchr(password, '|');
if (opts) {
*opts = 0;
opts++;
} else
opts = "";
/* Start asking for password */
prompt = "agent-pass";
for (retries = 0; retries < 3; retries++) {
res = ast_app_getdata(chan, prompt, passwd, sizeof(passwd) - 2, 0);
if (res < 0)
break;
res = 0;
if (password[0] == '/') {
/* 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;
}
}
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))
break;
}
prompt="auth-incorrect";
}
if ((retries < 3) && !res) {
if (strchr(opts, 'a'))
ast_cdr_setaccount(chan, passwd);
res = ast_streamfile(chan, "auth-thankyou", chan->language);
if (!res)
res = ast_waitstream(chan, "");
} else {
if (!res)
res = ast_streamfile(chan, "vm-goodbye", chan->language);
if (!res)
res = ast_waitstream(chan, "");
res = -1;
}
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, auth_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,66 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Applictions connected with CDR engine
*
* Copyright (C) 2003, Digium
*
* Martin Pycko <martinp@digium.com>
*
* 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/module.h>
#include <asterisk/pbx.h>
#include <stdlib.h>
static char *tdesc = "Make sure asterisk doesn't save CDR for a certain call";
static char *nocdr_descrip = "NoCDR(): makes sure there won't be any CDR written for a certain call";
static char *nocdr_app = "NoCDR";
static char *nocdr_synopsis = "Make sure asterisk doesn't save CDR for a certain call";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int nocdr_exec(struct ast_channel *chan, void *data)
{
if (chan->cdr) {
ast_cdr_free(chan->cdr);
chan->cdr = NULL;
}
return 0;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(nocdr_app);
}
int load_module(void)
{
return ast_register_application(nocdr_app, nocdr_exec, nocdr_synopsis, nocdr_descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,133 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Check if Channel is Available
*
* Copyright (C) 2003, Digium
*
* Mark Spencer <markster@digium.com>
* James Golovich <james@gnuinter.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/module.h>
#include <asterisk/app.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <pthread.h>
static char *tdesc = "Check if channel is available";
static char *app = "ChanIsAvail";
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\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;
LOCAL_USER_DECL;
static int chanavail_exec(struct ast_channel *chan, void *data)
{
int res=-1;
struct localuser *u;
char info[256], *peers, *tech, *number, *rest, *cur;
struct ast_channel *tempchan;
if (!data) {
ast_log(LOG_WARNING, "ChanIsAvail requires an argument (Zap/1&Zap/2)\n");
return -1;
}
LOCAL_USER_ADD(u);
strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1);
peers = info;
if (peers) {
cur = peers;
do {
/* remember where to start next time */
rest = strchr(cur, '&');
if (rest) {
*rest = 0;
rest++;
}
tech = cur;
number = strchr(tech, '/');
if (!number) {
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);
ast_hangup(tempchan);
tempchan = NULL;
res = 1;
break;
}
cur = rest;
} while (cur);
}
if (res < 1) {
pbx_builtin_setvar_helper(chan, "AVAILCHAN", "");
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
chan->priority+=100;
else
return -1;
}
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, chanavail_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,198 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Cut application
*
* Copyright (c) 2003 Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <app_cut__v002@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 = "Cuts up variables";
static char *app_cut = "Cut";
static char *cut_synopsis = "Cut(newvar=varname|delimiter|fieldspec)";
static char *cut_descrip =
"Cut(newvar=varname,delimiter,field)\n"
" newvar - new variable created from result string\n"
" varname - variable you want cut\n"
" delimiter - defaults to '-'\n"
" fieldspec - number of the field you want (1-based offset)\n"
" may also be specified as a range (with -)\n"
" or group of ranges and fields (with &)\n"
" Returns 0 or -1 on hangup or error.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int cut_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char *s, *newvar=NULL, *varname=NULL, *delimiter=NULL, *field=NULL;
int args_okay = 0;
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')) {
varname = strsep(&s, "|");
if (varname && (varname[0] != '\0')) {
delimiter = strsep(&s, "|");
if (delimiter) {
field = strsep(&s, "|");
if (field) {
args_okay = 1;
}
}
}
}
} else {
ast_log(LOG_ERROR, "Out of memory\n");
res = -1;
}
}
if (args_okay) {
char d, ds[2];
char *tmp = alloca(strlen(varname) + 4);
char *tmp2 = alloca(MAXRESULT);
char retstring[MAXRESULT];
memset(retstring, 0, MAXRESULT);
if (tmp && tmp2) {
snprintf(tmp, strlen(varname) + 4, "${%s}", varname);
memset(tmp2, 0, sizeof(tmp2));
} else {
ast_log(LOG_ERROR, "Out of memory");
return -1;
}
if (delimiter[0])
d = delimiter[0];
else
d = '-';
/* String form of the delimiter, for use with strsep(3) */
sprintf(ds,"%c",d);
pbx_substitute_variables_helper(chan, tmp, tmp2, MAXRESULT - 1);
if (tmp2) {
int curfieldnum = 1;
while ((tmp2 != NULL) && (field != NULL)) {
char *nextgroup = strsep(&field, "&");
int num1 = 0, num2 = MAXRESULT;
char trashchar;
if (sscanf(nextgroup, "%d-%d", &num1, &num2) == 2) {
/* range with both start and end */
} else if (sscanf(nextgroup, "-%d", &num2) == 1) {
/* range with end */
num1 = 0;
} else if ((sscanf(nextgroup, "%d%c", &num1, &trashchar) == 2) && (trashchar == '-')) {
/* range with start */
num2 = MAXRESULT;
} else if (sscanf(nextgroup, "%d", &num1) == 1) {
/* single number */
num2 = num1;
} else {
ast_log(LOG_ERROR, "Cut(): Illegal range '%s'\n", nextgroup);
ast_log(LOG_ERROR, "Usage: %s\n", cut_synopsis);
return -1;
}
/* Get to start, if any */
if (num1 > 0) {
while ((tmp2 != (char *)NULL + 1) && (curfieldnum < num1)) {
tmp2 = index(tmp2, d) + 1;
curfieldnum++;
}
}
/* Most frequent problem is the expectation of reordering fields */
if ((num1 > 0) && (curfieldnum > num1)) {
ast_log(LOG_WARNING, "Cut(): we're already past the field you wanted?\n");
}
/* Re-null tmp2 if we added 1 to NULL */
if (tmp2 == (char *)NULL + 1)
tmp2 = NULL;
/* Output fields until we either run out of fields or num2 is reached */
while ((tmp2 != NULL) && (curfieldnum <= num2)) {
char *tmp3 = strsep(&tmp2, ds);
int curlen = strlen(retstring);
if (strlen(retstring)) {
snprintf(retstring + curlen, MAXRESULT - curlen, "%c%s", d, tmp3);
} else {
snprintf(retstring, MAXRESULT, "%s", tmp3);
}
curfieldnum++;
}
}
}
pbx_builtin_setvar_helper(chan, newvar, retstring);
}
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app_cut);
}
int load_module(void)
{
return ast_register_application(app_cut, cut_exec, cut_synopsis, cut_descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,84 +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/module.h>
#include <asterisk/say.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Date and Time";
static char *app = "DateTime";
static char *synopsis = "Say the date and time";
static char *descrip =
" DateTime(): Says the current date and time. Returns -1 on hangup or 0\n"
"otherwise.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int datetime_exec(struct ast_channel *chan, void *data)
{
int res=0;
time_t t;
struct localuser *u;
LOCAL_USER_ADD(u);
time(&t);
if (chan->_state != AST_STATE_UP)
res = ast_answer(chan);
if (!res)
res = ast_say_datetime(chan, t, "", chan->language);
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, datetime_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,316 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Database access functions
*
* Copyright (C) 1999, Mark Spencer
* Copyright (C) 2003, Jefferson Noxon
*
* Mark Spencer <markster@linux-support.net>
* Jefferson Noxon <jeff@debian.org>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <sys/types.h>
#include <asterisk/options.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/pbx.h>
#include <asterisk/astdb.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";
static char *p_descrip =
" 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";
static char *dt_descrip =
" 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";
static char *d_app = "DBdel";
static char *dt_app = "DBdeltree";
static char *g_synopsis = "Retrieve a value from the database";
static char *p_synopsis = "Store a value in the database";
static char *d_synopsis = "Delete a key from the database";
static char *dt_synopsis = "Delete a family or keytree from the database";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int
deltree_exec (struct ast_channel *chan, void *data)
{
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;
}
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;
}
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 (ast_db_deltree (family, keytree))
{
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3
"DBdeltree: Error deleting key from database.\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;
}
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");
}
return 0;
}
static int
put_exec (struct ast_channel *chan, void *data)
{
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;
}
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");
}
return 0;
}
static int
get_exec (struct ast_channel *chan, void *data)
{
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;
}
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");
}
return 0;
}
int
unload_module (void)
{
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);
return retval;
}
int
load_module (void)
{
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;
}
char *
description (void)
{
return tdesc;
}
int
usecount (void)
{
int res;
STANDARD_USECOUNT (res);
return res;
}
char *
key ()
{
return ASTERISK_GPL_KEY;
}

File diff suppressed because it is too large Load Diff

View File

@@ -11,7 +11,6 @@
* the GNU General Public License
*/
#include <asterisk/lock.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
@@ -25,7 +24,6 @@
#include <pthread.h>
#include <stdio.h>
#include "../asterisk.h"
#include "../astconf.h"
static char *tdesc = "Extension Directory";
static char *app = "Directory";
@@ -35,7 +33,7 @@ static char *descrip =
" 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"
"specifies the context in which to interpret the extensions\n. 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";
@@ -112,6 +110,7 @@ static char *convert(char *lastname)
case 'Z':
tmp[lcount++] = '9';
break;
default:
}
lastname++;
}
@@ -127,17 +126,12 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *
struct ast_variable *v;
int res;
int found=0;
char *start, *pos, *conv,*stringp=NULL;
char *start, *pos, *conv;
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));
ext[0] = digit;
res = 0;
if (ast_readstring(chan, ext + 1, NUMDIGITS - 1, 3000, 3000, "#") < 0) res = -1;
if (ast_readstring(chan, ext + 1, NUMDIGITS, 3000, 3000, "#") < 0) res = -1;
if (!res) {
/* Search for all names which start with those digits */
v = ast_variable_browse(cfg, context);
@@ -147,9 +141,8 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *
/* Find a candidate extension */
start = strdup(v->value);
if (start) {
stringp=start;
strsep(&stringp, ",");
pos = strsep(&stringp, ",");
strtok(start, ",");
pos = strtok(NULL, ",");
if (pos) {
/* Grab the last name */
if (strrchr(pos, ' '))
@@ -172,22 +165,14 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *
}
if (v) {
/* We have a match -- play a greeting if they have it */
/* 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) {
snprintf(fn, sizeof(fn), "%s/vm/%s/greet", AST_SPOOL_DIR, v->name);
if (ast_fileexists(fn, NULL, chan->language)) {
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);
res = ast_say_digit_str(chan, v->name, chan->language);
}
ahem:
if (!res)
@@ -199,9 +184,9 @@ ahem:
ast_stopstream(chan);
if (res > -1) {
if (res == '1') {
strncpy(chan->exten, v->name, sizeof(chan->exten)-1);
strncpy(chan->exten, v->name, sizeof(chan->exten));
chan->priority = 0;
strncpy(chan->context, context, sizeof(chan->context)-1);
strncpy(chan->context, context, sizeof(chan->context));
res = 0;
break;
} else if (res == '*') {
@@ -243,8 +228,6 @@ static int directory_exec(struct ast_channel *chan, void *data)
}
LOCAL_USER_ADD(u);
top:
if (chan->_state != AST_STATE_UP)
res = ast_answer(chan);
if (!res)
res = ast_streamfile(chan, "dir-intro", chan->language);
if (!res)

View File

@@ -7,13 +7,10 @@
*
* Jim Dixon <jim@lambdatel.com>
*
* Made only slightly more sane by 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>
@@ -28,9 +25,7 @@
#include <pthread.h>
#include <sys/time.h>
/*
#define TONE_BLOCK_SIZE 320
*/
#define TONE_BLOCK_SIZE 200
static char *tdesc = "DISA (Direct Inward System Access) Application";
@@ -66,13 +61,7 @@ static char *descrip =
"The file that contains the passcodes (if used) allows specification\n"
"of either just a passcode (defaulting to the \"disa\" context, or\n"
"passcode|context on each line of the file. The file may contain blank\n"
"lines, or comments starting with \"#\" or \";\". In addition, the\n"
"above arguments may have |new-callerid-string appended to them, to\n"
"specify a new (different) callerid to be used for this call, for\n"
"example: numeric-passcode|context|\"My Phone\" <(234) 123-4567> or \n"
"full-pathname-of-passcode-file|\"My Phone\" <(234) 123-4567>. Note that\n"
"in the case of specifying the numeric-passcode, the context must be\n"
"specified if the callerid is specified also.\n\n"
"lines, or comments starting with \"#\" or \";\".\n\n"
"If login is successful, the application parses the dialed number in\n"
"the specified (or default) context, and returns 0 with the new extension\n"
"context filled-in and the priority set to 1, so that the PBX may\n"
@@ -83,21 +72,23 @@ STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static float loudness=4096.0;
static float loudness=8192.0;
static int firstdigittimeout = 20000; /* 20 seconds first digit timeout */
static int digittimeout = 10000; /* 10 seconds subsequent digit timeout */
int firstdigittimeout = 10000; /* 10 seconds first digit timeout */
int digittimeout = 5000; /* 5 seconds subsequent digit timeout */
static void make_tone_block(unsigned char *data, float f1, float f2, int len, int *x)
static void make_tone_block(unsigned char *data, float f1, float f2, int *x);
static void make_tone_block(unsigned char *data, float f1, float f2, int *x)
{
int i;
float val;
for(i = 0; i < len; i++)
for(i = 0; i < TONE_BLOCK_SIZE; 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);
data[i] = ast_lin2mu[(int)val + 32768];
}
/* wrap back around from 8000 */
if (*x >= 8000) *x = 0;
@@ -117,17 +108,14 @@ static int disa_exec(struct ast_channel *chan, void *data)
{
int i,j,k,x;
struct localuser *u;
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;
char tmp[256],exten[AST_MAX_EXTENSION];
unsigned char tone_block[TONE_BLOCK_SIZE],sil_block[TONE_BLOCK_SIZE];
char *ourcontext;
struct ast_frame *f,wf;
struct timeval lastout, now, lastdigittime;
int res;
fd_set readfds;
int waitfor_notime;
struct timeval notime = { 0,0 }, lastout, now, lastdigittime;
FILE *fp;
char *stringp=NULL;
if (ast_set_write_format(chan,AST_FORMAT_ULAW))
{
@@ -140,37 +128,28 @@ static int disa_exec(struct ast_channel *chan, void *data)
return -1;
}
lastout.tv_sec = lastout.tv_usec = 0;
/* make block of silence */
memset(sil_block,0x7f,TONE_BLOCK_SIZE);
if (!data || !strlen((char *)data)) {
ast_log(LOG_WARNING, "disa requires an argument (passcode/passcode file)\n");
return -1;
}
strncpy(tmp, (char *)data, sizeof(tmp)-1);
stringp=tmp;
strsep(&stringp, "|");
ourcontext = strsep(&stringp, "|");
/* if context specified, save 2nd arg and parse third */
if (ourcontext) {
strcpy(arg2,ourcontext);
ourcallerid = strsep(&stringp,"|");
}
strncpy(tmp, (char *)data, sizeof(tmp));
strtok(tmp, "|");
ourcontext = strtok(NULL, "|");
/* if context not specified, use "disa" */
else {
arg2[0] = 0;
ourcallerid = NULL;
ourcontext = "disa";
}
if (!ourcontext) ourcontext = "disa";
LOCAL_USER_ADD(u);
if (chan->_state != AST_STATE_UP)
if (chan->state != AST_STATE_UP)
{
/* answer */
ast_answer(chan);
}
i = k = x = 0; /* k is 0 for pswd entry, 1 for ext entry */
exten[0] = 0;
acctcode[0] = 0;
/* can we access DISA without password? */
if (!strcasecmp(tmp, "no-password"))
{;
{
k = 1;
ast_log(LOG_DEBUG, "DISA no-password login success\n");
}
@@ -184,13 +163,35 @@ static int disa_exec(struct ast_channel *chan, void *data)
{
ast_log(LOG_DEBUG,"DISA %s entry timeout on chan %s\n",
((k) ? "extension" : "password"),chan->name);
break;
goto reorder;
}
if ((res = ast_waitfor(chan, -1) < 0)) {
ast_log(LOG_DEBUG, "Waitfor returned %d\n", res);
continue;
/* if first digit or ignore, send dialtone */
if ((!i) || (ast_ignore_pattern(ourcontext,exten) && k))
{
gettimeofday(&now,NULL);
if (lastout.tv_sec &&
(ms_diff(&now,&lastout) < 25)) continue;
lastout.tv_sec = now.tv_sec;
lastout.tv_usec = now.tv_usec;
wf.frametype = AST_FRAME_VOICE;
wf.subclass = AST_FORMAT_ULAW;
wf.offset = AST_FRIENDLY_OFFSET;
wf.mallocd = 0;
wf.data = tone_block;
wf.datalen = TONE_BLOCK_SIZE;
/* make this tone block */
make_tone_block(tone_block,350.0,440.0,&x);
wf.timelen = wf.datalen / 8;
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;
}
}
waitfor_notime = notime.tv_usec + notime.tv_sec * 1000;
if (!ast_waitfor_nandfds(&chan, 1, &(chan->fds[0]), 1, NULL, NULL,
&waitfor_notime)) continue;
f = ast_read(chan);
if (f == NULL)
{
@@ -203,27 +204,6 @@ static int disa_exec(struct ast_channel *chan, void *data)
ast_frfree(f);
LOCAL_USER_REMOVE(u);
return -1;
}
if (f->frametype == AST_FRAME_VOICE) {
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 */
if (f->frametype != AST_FRAME_DTMF)
@@ -231,10 +211,8 @@ static int disa_exec(struct ast_channel *chan, void *data)
ast_frfree(f);
continue;
}
j = f->subclass; /* save digit */
ast_frfree(f);
gettimeofday(&lastdigittime,NULL);
/* got a DTMF tone */
if (i < AST_MAX_EXTENSION) /* if still valid number of digits */
@@ -256,7 +234,6 @@ static int disa_exec(struct ast_channel *chan, void *data)
tmp[0] = 0;
while(fgets(tmp,sizeof(tmp) - 1,fp))
{
char *stringp=NULL,*stringp2;
if (!tmp[0]) continue;
if (tmp[strlen(tmp) - 1] == '\n')
tmp[strlen(tmp) - 1] = 0;
@@ -264,14 +241,8 @@ static int disa_exec(struct ast_channel *chan, void *data)
/* skip comments */
if (tmp[0] == '#') continue;
if (tmp[0] == ';') continue;
stringp=tmp;
strsep(&stringp, "|");
stringp2=strsep(&stringp, "|");
if (stringp2) {
ourcontext=stringp2;
stringp2=strsep(&stringp, "|");
if (stringp2) ourcallerid=stringp2;
}
strtok(tmp, "|");
ourcontext = strtok(NULL, "|");
/* password must be in valid format (numeric) */
if (sscanf(tmp,"%d",&j) < 1) continue;
/* if we got it */
@@ -284,14 +255,10 @@ static int disa_exec(struct ast_channel *chan, void *data)
{
ast_log(LOG_WARNING,"DISA on chan %s got bad password %s\n",chan->name,exten);
goto reorder;
}
/* password good, set to dial state */
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;
strcpy(acctcode,exten);
exten[0] = 0;
ast_log(LOG_DEBUG,"Successful DISA log-in on chan %s\n",chan->name);
continue;
@@ -301,71 +268,108 @@ static int disa_exec(struct ast_channel *chan, void *data)
exten[i] = 0;
if (!k) continue; /* if getting password, continue doing it */
/* if this exists */
/* if can do some more, do it */
if (!ast_matchmore_extension(chan,ourcontext,exten,1, chan->callerid))
break;
}
}
if (k && ast_exists_extension(chan,ourcontext,exten,1, chan->callerid))
{
/* We're authenticated and have a valid extension */
if (ourcallerid && *ourcallerid)
{
if (chan->callerid) free(chan->callerid);
chan->callerid = strdup(ourcallerid);
}
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);
return 0;
}
reorder:
/* 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))
if (ast_exists_extension(chan,ourcontext,exten,1, chan->callerid))
{
ast_log(LOG_WARNING, "DISA Failed to write frame on %s\n",chan->name);
strcpy(chan->exten,exten);
strcpy(chan->context,ourcontext);
chan->priority = 0;
LOCAL_USER_REMOVE(u);
return -1;
return 0;
}
/* if can do some more, do it */
if (ast_canmatch_extension(chan,ourcontext,exten,1, chan->callerid)) continue;
}
reorder:
/* something is invalid, give em reorder forever */
x = 0;
for(;;)
{
for(i = 0; i < 10; i++)
{
do gettimeofday(&now,NULL);
while (lastout.tv_sec &&
(ms_diff(&now,&lastout) < 25)) ;
lastout.tv_sec = now.tv_sec;
lastout.tv_usec = now.tv_usec;
wf.frametype = AST_FRAME_VOICE;
wf.subclass = AST_FORMAT_ULAW;
wf.offset = AST_FRIENDLY_OFFSET;
wf.mallocd = 0;
wf.data = tone_block;
wf.datalen = TONE_BLOCK_SIZE;
/* make this tone block */
make_tone_block(tone_block,480.0,620.0,&x);
wf.timelen = wf.datalen / 8;
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;
}
FD_ZERO(&readfds);
FD_SET(chan->fds[0],&readfds);
/* if no read avail, do send again */
if (select(chan->fds[0] + 1,&readfds,NULL,
NULL,&notime) < 1) continue;
/* read frame */
f = ast_read(chan);
if (f == NULL)
{
LOCAL_USER_REMOVE(u);
return -1;
}
if ((f->frametype == AST_FRAME_CONTROL) &&
(f->subclass == AST_CONTROL_HANGUP))
{
ast_frfree(f);
LOCAL_USER_REMOVE(u);
return -1;
}
ast_frfree(f);
}
for(i = 0; i < 10; i++)
{
do gettimeofday(&now,NULL);
while (lastout.tv_sec &&
(ms_diff(&now,&lastout) < 25)) ;
lastout.tv_sec = now.tv_sec;
lastout.tv_usec = now.tv_usec;
wf.frametype = AST_FRAME_VOICE;
wf.subclass = AST_FORMAT_ULAW;
wf.offset = AST_FRIENDLY_OFFSET;
wf.mallocd = 0;
wf.data = sil_block;
wf.datalen = TONE_BLOCK_SIZE;
wf.timelen = wf.datalen / 8;
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;
}
FD_ZERO(&readfds);
FD_SET(chan->fds[0],&readfds);
/* if no read avail, do send again */
if (select(chan->fds[0] + 1,&readfds,NULL,
NULL,&notime) < 1) continue;
/* read frame */
f = ast_read(chan);
if (f == NULL)
{
LOCAL_USER_REMOVE(u);
return -1;
}
if ((f->frametype == AST_FRAME_CONTROL) &&
(f->subclass == AST_CONTROL_HANGUP))
{
ast_frfree(f);
LOCAL_USER_REMOVE(u);
return -1;
}
ast_frfree(f);
}
}
ast_frfree(f);
}
LOCAL_USER_REMOVE(u);
return -1;
}
int unload_module(void)
@@ -391,7 +395,7 @@ int usecount(void)
return res;
}
char *key(void)
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -11,7 +11,6 @@
* the GNU General Public License
*/
#include <asterisk/lock.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
@@ -45,19 +44,11 @@ static int echo_exec(struct ast_channel *chan, void *data)
struct localuser *u;
struct ast_frame *f;
LOCAL_USER_ADD(u);
ast_set_write_format(chan, ast_best_codec(chan->nativeformats));
ast_set_read_format(chan, ast_best_codec(chan->nativeformats));
/* Do our thing here */
while(ast_waitfor(chan, -1) > -1) {
f = ast_read(chan);
if (!f)
break;
while((f = ast_read(chan))) {
if (f->frametype == AST_FRAME_VOICE) {
if (ast_write(chan, f))
break;
} else if (f->frametype == AST_FRAME_VIDEO) {
if (ast_write(chan, f))
break;
} else if (f->frametype == AST_FRAME_DTMF) {
if (f->subclass == '#') {
res = 0;

View File

@@ -1,205 +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/enum.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";
static char *synopsis = "Lookup number in ENUM";
static char *descrip =
" EnumLookup(exten): Looks up an extension via ENUM and sets\n"
"the variable 'ENUM'. For VoIP URIs this variable will \n"
"look like 'TECHNOLOGY/URI' with the appropriate technology.\n"
"Returns -1 on hangup, or 0 on completion regardless of whether the \n"
"lookup was successful. \n"
"Currently, the enumservices SIP, H323, IAX, IAX2 and TEL are recognized. \n"
"A good SIP, H323, IAX or IAX2 entry will result in normal priority handling, \n"
"whereas a good TEL entry will increase the priority by 51 (if existing).\n"
"If the lookup was *not* successful and there exists a priority n + 101,\n"
"then that priority will be taken next.\n" ;
#define ENUM_CONFIG "enum.conf"
static char h323driver[80];
#define H323DRIVERDEFAULT "H323"
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int enumlookup_exec(struct ast_channel *chan, void *data)
{
int res=0;
char tech[80];
char dest[80];
char tmp[256];
char *c,*t;
struct localuser *u;
if (!data || !strlen(data)) {
ast_log(LOG_WARNING, "EnumLookup requires an argument (extension)\n");
res = 1;
}
LOCAL_USER_ADD(u);
if (!res) {
res = ast_get_enum(chan, data, dest, sizeof(dest), tech, sizeof(tech));
printf("ENUM got '%d'\n", res);
}
LOCAL_USER_REMOVE(u);
/* Parse it out */
if (res > 0) {
if (!strcasecmp(tech, "SIP")) {
c = dest;
if (!strncmp(c, "sip:", 4))
c += 4;
snprintf(tmp, sizeof(tmp), "SIP/%s", c);
pbx_builtin_setvar_helper(chan, "ENUM", tmp);
} else if (!strcasecmp(tech, "h323")) {
c = dest;
if (!strncmp(c, "h323:", 5))
c += 5;
snprintf(tmp, sizeof(tmp), "%s/%s", h323driver, c);
/* do a s!;.*!! on the H323 URI */
t = strchr(c,';');
if (t)
*t = 0;
pbx_builtin_setvar_helper(chan, "ENUM", tmp);
} else if (!strcasecmp(tech, "iax")) {
c = dest;
if (!strncmp(c, "iax:", 4))
c += 4;
snprintf(tmp, sizeof(tmp), "IAX/%s", c);
pbx_builtin_setvar_helper(chan, "ENUM", tmp);
} else if (!strcasecmp(tech, "iax2")) {
c = dest;
if (!strncmp(c, "iax2:", 5))
c += 5;
snprintf(tmp, sizeof(tmp), "IAX2/%s", c);
pbx_builtin_setvar_helper(chan, "ENUM", tmp);
} else if (!strcasecmp(tech, "tel")) {
c = dest;
if (!strncmp(c, "tel:", 4))
c += 4;
if (c[0] != '+') {
ast_log(LOG_NOTICE, "tel: uri must start with a \"+\" (got '%s')\n", c);
res = 0;
} else {
/* now copy over the number, skipping all non-digits and stop at ; or NULL */
t = tmp;
while( *c && (*c != ';') && (t - tmp < (sizeof(tmp) - 1))) {
if (isdigit(*c))
*t++ = *c;
c++;
}
*t = 0;
pbx_builtin_setvar_helper(chan, "ENUM", tmp);
ast_log(LOG_NOTICE, "tel: ENUM set to \"%s\"\n", tmp);
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 51, chan->callerid))
chan->priority += 50;
else
res = 0;
}
} else if (strlen(tech)) {
ast_log(LOG_NOTICE, "Don't know how to handle technology '%s'\n", tech);
res = 0;
}
}
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"))) {
strcpy(h323driver, H323DRIVERDEFAULT);
} else {
strcpy(h323driver, s);
}
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, enumlookup_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;
}

View File

@@ -1,475 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Connect to festival
*
* Copyright (C) 2002, Christos Ricudis
*
* Christos Ricudis <ricudis@paiko.gr>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <sys/types.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/md5.h>
#include <asterisk/config.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <pthread.h>
#define FESTIVAL_CONFIG "festival.conf"
static char *tdesc = "Simple Festival Interface";
static char *app = "Festival";
static char *synopsis = "Say text to the user";
static char *descrip =
" Festival(text[|intkeys]): Connect to Festival, send the argument, get back the waveform,"
"play it to the user, allowing any given interrupt keys to immediately terminate and return\n"
"the value, or 'any' to allow any number back (useful in dialplan)\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static char *socket_receive_file_to_buff(int fd,int *size)
{
/* Receive file (probably a waveform file) from socket using */
/* Festival key stuff technique, but long winded I know, sorry */
/* but will receive any file without closeing the stream or */
/* using OOB data */
static char *file_stuff_key = "ft_StUfF_key"; /* must == Festival's key */
char *buff;
int bufflen;
int n,k,i;
char c;
bufflen = 1024;
buff = (char *)malloc(bufflen);
*size=0;
for (k=0; file_stuff_key[k] != '\0';)
{
n = read(fd,&c,1);
if (n==0) break; /* hit stream eof before end of file */
if ((*size)+k+1 >= bufflen)
{ /* +1 so you can add a NULL if you want */
bufflen += bufflen/4;
buff = (char *)realloc(buff,bufflen);
}
if (file_stuff_key[k] == c)
k++;
else if ((c == 'X') && (file_stuff_key[k+1] == '\0'))
{ /* It looked like the key but wasn't */
for (i=0; i < k; i++,(*size)++)
buff[*size] = file_stuff_key[i];
k=0;
/* omit the stuffed 'X' */
}
else
{
for (i=0; i < k; i++,(*size)++)
buff[*size] = file_stuff_key[i];
k=0;
buff[*size] = c;
(*size)++;
}
}
return buff;
}
static int send_waveform_to_fd(char *waveform, int length, int fd) {
int res;
int x;
#ifdef __PPC__
char c;
#endif
res = fork();
if (res < 0)
ast_log(LOG_WARNING, "Fork failed\n");
if (res)
return res;
for (x=0;x<256;x++) {
if (x != fd)
close(x);
}
//IAS
#ifdef __PPC__
for( x=0; x<length; x+=2)
{
c = *(waveform+x+1);
*(waveform+x+1)=*(waveform+x);
*(waveform+x)=c;
}
#endif
write(fd,waveform,length);
write(fd,"a",1);
close(fd);
exit(0);
}
static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, int length, char *intkeys) {
int res=0;
int fds[2];
int ms = -1;
int pid = -1;
int needed = 0;
int owriteformat;
struct ast_frame *f;
struct myframe {
struct ast_frame f;
char offset[AST_FRIENDLY_OFFSET];
char frdata[2048];
} myf;
if (pipe(fds)) {
ast_log(LOG_WARNING, "Unable to create pipe\n");
return -1;
}
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=send_waveform_to_fd(waveform,length,fds[1]);
if (res >= 0) {
pid = res;
/* Order is important -- there's almost always going to be mp3... we want to prioritize the
user */
for (;;) {
ms = 1000;
res = ast_waitfor(chan, ms);
if (res < 1) {
res = -1;
break;
}
f = ast_read(chan);
if (!f) {
ast_log(LOG_WARNING, "Null frame == hangup() detected\n");
res = -1;
break;
}
if (f->frametype == AST_FRAME_DTMF) {
ast_log(LOG_DEBUG, "User pressed a key\n");
if (intkeys && strchr(intkeys, f->subclass)) {
res = f->subclass;
ast_frfree(f);
break;
}
}
if (f->frametype == AST_FRAME_VOICE) {
/* Treat as a generator */
needed = f->samples * 2;
if (needed > sizeof(myf.frdata)) {
ast_log(LOG_WARNING, "Only able to deliver %d of %d requested samples\n",
sizeof(myf.frdata) / 2, needed/2);
needed = sizeof(myf.frdata);
}
res = read(fds[0], myf.frdata, needed);
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.data = myf.frdata;
if (ast_write(chan, &myf.f) < 0) {
res = -1;
break;
}
if (res < needed) { // last frame
ast_log(LOG_DEBUG, "Last frame\n");
res=0;
break;
}
} else {
ast_log(LOG_DEBUG, "No more waveform\n");
res = 0;
}
}
ast_frfree(f);
}
}
close(fds[0]);
close(fds[1]);
// if (pid > -1)
// kill(pid, SIGKILL);
if (!res && owriteformat)
ast_set_write_format(chan, owriteformat);
return res;
}
#define MAXLEN 180
#define MAXFESTLEN 2048
static int festival_exec(struct ast_channel *chan, void *vdata)
{
int usecache;
int res=0;
struct localuser *u;
struct sockaddr_in serv_addr;
struct hostent *serverhost;
int fd;
FILE *fs;
char *host;
char *cachedir;
char *temp;
char *festivalcommand;
int port=1314;
int n;
char ack[4];
char *waveform;
int filesize;
int wave;
char bigstring[MAXFESTLEN];
int i;
struct MD5Context md5ctx;
unsigned char MD5Res[16];
char MD5Hex[32];
char koko[4];
char cachefile[MAXFESTLEN];
int readcache=0;
int writecache=0;
int strln;
int fdesc = -1;
char buffer[16384];
int seekpos = 0;
char data[256] = "";
char *intstr;
struct ast_config *cfg;
cfg = ast_load(FESTIVAL_CONFIG);
if (!cfg) {
ast_log(LOG_WARNING, "No such configuration file %s\n", FESTIVAL_CONFIG);
return -1;
}
if (!(host = ast_variable_retrieve(cfg, "general", "host"))) {
host = "localhost";
}
if (!(temp = ast_variable_retrieve(cfg, "general", "port"))) {
port = 1314;
} else {
port = atoi(temp);
}
if (!(temp = ast_variable_retrieve(cfg, "general", "usecache"))) {
usecache=0;
} else {
usecache = ast_true(temp);
}
if (!(cachedir = ast_variable_retrieve(cfg, "general", "cachedir"))) {
cachedir = "/tmp/";
}
if (!(festivalcommand = ast_variable_retrieve(cfg, "general", "festivalcommand"))) {
festivalcommand = "(tts_textasterisk \"%s\" 'file)(quit)\n";
}
if (!vdata || !strlen(vdata)) {
ast_log(LOG_WARNING, "festival requires an argument (text)\n");
return -1;
}
strncpy(data, vdata, sizeof(data) - 1);
if ((intstr = strchr(data, '|'))) {
*intstr = '\0';
intstr++;
if (!strcasecmp(intstr, "any"))
intstr = AST_DIGIT_ANY;
}
LOCAL_USER_ADD(u);
ast_log(LOG_DEBUG, "Text passed to festival server : %s\n",(char *)data);
/* Connect to local festival server */
fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fd < 0) {
ast_log(LOG_WARNING,"festival_client: can't get socket\n");
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 = gethostbyname(host);
if (serverhost == (struct hostent *)0) {
ast_log(LOG_WARNING,"festival_client: gethostbyname failed\n");
return -1;
}
memmove(&serv_addr.sin_addr,serverhost->h_addr, serverhost->h_length);
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) {
ast_log(LOG_WARNING,"festival_client: connect to server failed\n");
return -1;
}
/* Compute MD5 sum of string */
MD5Init(&md5ctx);
MD5Update(&md5ctx,(unsigned char const *)data,strlen(data));
MD5Final(MD5Res,&md5ctx);
strcpy(MD5Hex,"");
/* Convert to HEX and look if there is any matching file in the cache
directory */
for (i=0;i<16;i++) {
sprintf(koko,"%X",MD5Res[i]);
strcat(MD5Hex,koko);
}
readcache=0;
writecache=0;
if (strlen(cachedir)+strlen(MD5Hex)+1<=MAXFESTLEN && (usecache==-1)) {
sprintf(cachefile,"%s/%s",cachedir,MD5Hex);
fdesc=open(cachefile,O_RDWR);
if (fdesc==-1) {
fdesc=open(cachefile,O_CREAT|O_RDWR,0);
if (fdesc!=-1) {
writecache=1;
strln=strlen((char *)data);
ast_log(LOG_DEBUG,"line length : %d\n",strln);
write(fdesc,&strln,sizeof(int));
write(fdesc,data,strln);
seekpos=lseek(fdesc,0,SEEK_CUR);
ast_log(LOG_DEBUG,"Seek position : %d\n",seekpos);
}
} else {
read(fdesc,&strln,sizeof(int));
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);
if (strcmp(bigstring,data)==0) {
readcache=1;
} else {
ast_log(LOG_WARNING,"Strings do not match\n");
}
} else {
ast_log(LOG_WARNING,"Size mismatch\n");
}
}
}
if (readcache==1) {
close(fd);
fd=fdesc;
ast_log(LOG_DEBUG,"Reading from cache...\n");
} else {
ast_log(LOG_DEBUG,"Passing text to festival...\n");
fs=fdopen(dup(fd),"wb");
fprintf(fs,festivalcommand,(char *)data);
fflush(fs);
fclose(fs);
}
/* Write to cache and then pass it down */
if (writecache==1) {
ast_log(LOG_DEBUG,"Writing result to cache...\n");
while ((strln=read(fd,buffer,16384))!=0) {
write(fdesc,buffer,strln);
}
close(fd);
close(fdesc);
fd=open(cachefile,O_RDWR);
lseek(fd,seekpos,SEEK_SET);
}
ast_log(LOG_DEBUG,"Passing data to channel...\n");
/* Read back info from server */
/* This assumes only one waveform will come back, also LP is unlikely */
wave = 0;
do {
for (n=0; n < 3; )
n += read(fd,ack+n,3-n);
ack[3] = '\0';
if (strcmp(ack,"WV\n") == 0) { /* receive a waveform */
ast_log(LOG_DEBUG,"Festival WV command\n");
waveform = socket_receive_file_to_buff(fd,&filesize);
res = send_waveform_to_channel(chan,waveform,filesize, intstr);
free(waveform);
break;
}
else if (strcmp(ack,"LP\n") == 0) { /* receive an s-expr */
ast_log(LOG_DEBUG,"Festival LP command\n");
waveform = socket_receive_file_to_buff(fd,&filesize);
waveform[filesize]='\0';
ast_log(LOG_WARNING,"Festival returned LP : %s\n",waveform);
free(waveform);
} else if (strcmp(ack,"ER\n") == 0) { /* server got an error */
ast_log(LOG_WARNING,"Festival returned ER\n");
res=-1;
break;
}
} while (strcmp(ack,"OK\n") != 0);
close(fd);
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, festival_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,116 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* App to flash a zap trunk
*
* 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/module.h>
#include <asterisk/translate.h>
#include <asterisk/image.h>
#include <asterisk/options.h>
#include <sys/ioctl.h>
#include <linux/zaptel.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Flash zap trunk application";
static char *app = "Flash";
static char *synopsis = "Flashes a Zap Trunk";
static char *descrip =
" Flash(): Sends a flash on a zap trunk. This is only a hack for\n"
"people who want to perform transfers and such via AGI and is generally\n"
"quite useless otherwise. Returns 0 on success or -1 if this is not\n"
"a zap trunk\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static inline int zt_wait_event(int fd)
{
/* Avoid the silly zt_waitevent which ignores a bunch of events */
int i,j=0;
i = ZT_IOMUX_SIGEVENT;
if (ioctl(fd, ZT_IOMUX, &i) == -1) return -1;
if (ioctl(fd, ZT_GETEVENT, &j) == -1) return -1;
return j;
}
static int flash_exec(struct ast_channel *chan, void *data)
{
int res = -1;
int x;
struct localuser *u;
struct zt_params ztp;
LOCAL_USER_ADD(u);
if (!strcasecmp(chan->type, "Zap")) {
memset(&ztp, 0, sizeof(ztp));
res = ioctl(chan->fds[0], ZT_GET_PARAMS, &ztp);
if (!res) {
if (ztp.sigtype & __ZT_SIG_FXS) {
x = ZT_FLASH;
res = ioctl(chan->fds[0], ZT_HOOK, &x);
if (!res || (errno == EINPROGRESS)) {
if (res) {
/* Wait for the event to finish */
zt_wait_event(chan->fds[0]);
}
res = ast_safe_sleep(chan, 1000);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Flashed channel %s\n", chan->name);
} else
ast_log(LOG_WARNING, "Unable to flash channel %s: %s\n", chan->name, strerror(errno));
} else
ast_log(LOG_WARNING, "%s is not an FXO Channel\n", chan->name);
} else
ast_log(LOG_WARNING, "Unable to get parameters of %s: %s\n", chan->name, strerror(errno));
} else
ast_log(LOG_WARNING, "%s is not a Zap channel\n", chan->name);
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, flash_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,149 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Execute arbitrary system commands
*
* 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/module.h>
#include <asterisk/adsi.h>
#include <asterisk/options.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Get ADSI CPE ID";
static char *app = "GetCPEID";
static char *synopsis = "Get ADSI CPE ID";
static char *descrip =
" 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;
LOCAL_USER_DECL;
static int cpeid_setstatus(struct ast_channel *chan, char *stuff[], int voice)
{
int justify[5] = { ADSI_JUST_CENT, ADSI_JUST_LEFT, ADSI_JUST_LEFT, ADSI_JUST_LEFT };
char *tmp[5];
int x;
for (x=0;x<4;x++)
tmp[x] = stuff[x];
tmp[4] = NULL;
return adsi_print(chan, tmp, justify, voice);
}
static int cpeid_exec(struct ast_channel *chan, void *idata)
{
int res=0;
struct localuser *u;
unsigned char cpeid[4];
int gotgeometry = 0;
int gotcpeid = 0;
int width, height, buttons;
char data[4][80];
char *stuff[4];
LOCAL_USER_ADD(u);
stuff[0] = data[0];
stuff[1] = data[1];
stuff[2] = data[2];
stuff[3] = data[3];
memset(data, 0, sizeof(data));
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);
res = adsi_get_cpeid(chan, cpeid, 0);
if (res > 0) {
gotcpeid = 1;
if (option_verbose > 2)
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) {
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) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "CPE has %d lines, %d columns, and %d buttons on '%s'\n", height, width, buttons, chan->name);
gotgeometry = 1;
}
}
if (res > -1) {
if (gotcpeid)
sprintf(stuff[1], "CPEID: %02x:%02x:%02x:%02x", cpeid[0], cpeid[1], cpeid[2], cpeid[3]);
else
strcpy(stuff[1], "CPEID Unknown");
if (gotgeometry)
sprintf(stuff[2], "Geom: %dx%d, %d buttons", width, height, buttons);
else
strcpy(stuff[2], "Geometry unknown");
strcpy(stuff[3], "Press # to exit");
cpeid_setstatus(chan, stuff, 1);
for(;;) {
res = ast_waitfordigit(chan, 1000);
if (res < 0)
break;
if (res == '#') {
res = 0;
break;
}
}
adsi_unload_session(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, cpeid_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,145 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* HasNewVoicemail application
*
* Copyright (c) 2003 Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <asterisk-hasnewvoicemail-app@the-tilghman.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.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 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 new voicemail"
" Optionally sets <varname> to the number of new messages.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int hasnewvoicemail_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char vmpath[256], *input, *varname = NULL, *vmbox, *context = "default";
DIR *vmdir;
struct dirent *vment;
int vmcount = 0;
if (!data) {
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) {
if ((vmbox = strsep(&input,"|")))
varname = input;
else
vmbox = input;
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 {
/* No matter what the format of VM, there will always be a .txt file for each message. */
while ((vment = readdir(vmdir)))
if (!strncmp(vment->d_name + 7,".txt",4))
vmcount++;
closedir(vmdir);
}
/* Set the count in the channel variable */
if (varname) {
char tmp[12];
snprintf(tmp, sizeof(tmp) - 1, "%d", vmcount);
pbx_builtin_setvar_helper(chan, varname, tmp);
}
if (vmcount > 0) {
/* Branch to the next extension */
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid)) {
chan->priority += 100;
} else
ast_log(LOG_WARNING, "VM box %s@%s has new voicemail, but extension %s, priority %d doesn't exist\n", vmbox, context, chan->exten, chan->priority + 101);
}
} else {
ast_log(LOG_ERROR, "Out of memory error\n");
}
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app_hasnewvoicemail);
}
int load_module(void)
{
return ast_register_application(app_hasnewvoicemail, hasnewvoicemail_exec, hasnewvoicemail_synopsis, hasnewvoicemail_descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -11,7 +11,6 @@
* the GNU General Public License
*/
#include <asterisk/lock.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>

View File

@@ -11,7 +11,6 @@
* the GNU General Public License
*/
#include <asterisk/lock.h>
#include <asterisk/file.h>
#include <asterisk/frame.h>
#include <asterisk/logger.h>
@@ -26,20 +25,10 @@
#include <stdlib.h>
#include <pthread.h>
#include <sys/time.h>
#ifdef __linux__
#include <linux/soundcard.h>
#elif defined(__FreeBSD__)
#include <machine/soundcard.h>
#else
#include <soundcard.h>
#endif
#include <netinet/in.h>
#ifdef __OpenBSD__
#define DEV_DSP "/dev/audio"
#else
#define DEV_DSP "/dev/dsp"
#endif
/* Number of 32 byte buffers -- each buffer is 2 ms */
#define BUFFER_SIZE 32
@@ -58,30 +47,30 @@ STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static ast_mutex_t sound_lock = AST_MUTEX_INITIALIZER;
static pthread_mutex_t sound_lock = PTHREAD_MUTEX_INITIALIZER;
static int sound = -1;
static int write_audio(short *data, int len)
{
int res;
struct audio_buf_info info;
ast_mutex_lock(&sound_lock);
ast_pthread_mutex_lock(&sound_lock);
if (sound < 0) {
ast_log(LOG_WARNING, "Sound device closed?\n");
ast_mutex_unlock(&sound_lock);
ast_pthread_mutex_unlock(&sound_lock);
return -1;
}
if (ioctl(sound, SNDCTL_DSP_GETOSPACE, &info)) {
ast_log(LOG_WARNING, "Unable to read output space\n");
ast_mutex_unlock(&sound_lock);
ast_pthread_mutex_unlock(&sound_lock);
return -1;
}
res = write(sound, data, len);
ast_mutex_unlock(&sound_lock);
ast_pthread_mutex_unlock(&sound_lock);
return res;
}
static int create_audio(void)
static int create_audio()
{
int fmt, desired, res, fd;
fd = open(DEV_DSP, O_WRONLY);

View File

@@ -1,115 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* App to lookup the callerid number, and see if it is blacklisted
*
* 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/options.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/translate.h>
#include <asterisk/image.h>
#include <asterisk/callerid.h>
#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";
static char *app = "LookupBlacklist";
static char *synopsis = "Look up Caller*ID name/number from blacklist database";
static char *descrip =
" LookupBlacklist: Looks up the Caller*ID number on the active\n"
"channel in the Asterisk database (family 'blacklist'). If the\n"
"number is found, and if there exists a priority n + 101,\n"
"where 'n' is the priority of the current instance, then the\n"
"channel will be setup to continue at that priority level.\n"
"Otherwise, it returns 0. Does nothing if no Caller*ID was received on the\n"
"channel.\n"
"Example: database put blacklist <name/number> 1\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int
lookupblacklist_exec (struct ast_channel *chan, void *data)
{
char old_cid[144] = "", *num, *name;
char blacklist[1];
char shrunknum[64] = "";
struct localuser *u;
int bl = 0;
LOCAL_USER_ADD (u);
if (chan->callerid)
{
strncpy (old_cid, chan->callerid, sizeof (old_cid) - 1);
ast_callerid_parse (old_cid, &name, &num);
if (num)
strncpy (shrunknum, num, sizeof (shrunknum) - 1);
else
num = shrunknum;
ast_shrink_phone_number (shrunknum);
if (!ast_db_get ("blacklist", shrunknum, blacklist, sizeof (blacklist)))
{
if (option_verbose > 2)
ast_log(LOG_NOTICE, "Blacklisted number %s found\n",shrunknum);
bl = 1;
}
else if (!ast_db_get ("blacklist", name, blacklist, sizeof (blacklist)))
{
if (option_verbose > 2)
ast_log (LOG_NOTICE,"Blacklisted name \"%s\" found\n",name);
bl = 1;
}
}
if (bl && ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
chan->priority+=100;
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, lookupblacklist_exec, synopsis,descrip);
}
char *description (void)
{
return tdesc;
}
int usecount (void)
{
int res;
STANDARD_USECOUNT (res);
return res;
}
char *key ()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,112 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* App to set callerid name from database, based on directory number
*
* 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/options.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/translate.h>
#include <asterisk/image.h>
#include <asterisk/callerid.h>
#include <asterisk/astdb.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Look up CallerID Name from local database";
static char *app = "LookupCIDName";
static char *synopsis = "Look up CallerID Name from local database";
static char *descrip =
" LookupCIDName: Looks up the Caller*ID number on the active\n"
"channel in the Asterisk database (family 'cidname') and sets the\n"
"Caller*ID name. Does nothing if no Caller*ID was received on the\n"
"channel. This is useful if you do not subscribe to Caller*ID\n"
"name delivery, or if you want to change the names on some incoming\n"
"calls. Always returns 0.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int
lookupcidname_exec (struct ast_channel *chan, void *data)
{
char old_cid[144] = "", *num, *name;
char new_cid[144];
char dbname[64];
char shrunknum[64] = "";
struct localuser *u;
LOCAL_USER_ADD (u);
if (chan->callerid)
{
strncpy (old_cid, chan->callerid, sizeof (old_cid) - 1);
ast_callerid_parse (old_cid, &name, &num); /* this destroys the original string */
if (num) /* It's possible to get an empty number */
strncpy (shrunknum, num, sizeof (shrunknum) - 1);
else
num = shrunknum;
ast_shrink_phone_number (shrunknum);
if (!ast_db_get ("cidname", shrunknum, dbname, sizeof (dbname)))
{
snprintf (new_cid, sizeof (new_cid), "\"%s\" <%s>", dbname, num);
ast_set_callerid (chan, new_cid, 0);
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID to %s\n",
new_cid);
}
}
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, lookupcidname_exec, synopsis,
descrip);
}
char *
description (void)
{
return tdesc;
}
int
usecount (void)
{
int res;
STANDARD_USECOUNT (res);
return res;
}
char *
key ()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,251 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Macro Implementation
*
* Copyright (C) 2003, Digium
*
* Mark Spencer <markster@digium.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <sys/types.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/options.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";
static char *descrip =
" Macro(macroname|arg1|arg2...): Executes a macro using the context\n"
"'macro-<macroname>', jumping to the 's' extension of that context and\n"
"executing each step, then returning when the steps end. The calling\n"
"extension, context, and priority are stored in ${MACRO_EXTEN}, \n"
"${MACRO_CONTEXT} and ${MACRO_PRIORITY} respectively. Arguments become\n"
"${ARG1}, ${ARG2}, etc in the macro context. Macro returns -1 if\n"
"any step in the macro returns -1, and 0 otherwise. If you Goto out\n"
"of the Macro context, the Macro will terminate and control will be return\n"
"at the location of the Goto. Otherwise if ${MACRO_OFFSET} is set at\n"
"termination, Macro will attempt to continue at priority\n"
"MACRO_OFFSET + N + 1 if such a step exists, and N + 1 otherwise.\n";
static char *app = "Macro";
static char *synopsis = "Macro Implementation";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int macro_exec(struct ast_channel *chan, void *data)
{
char tmp[256] = "";
char *cur, *rest;
char *macro;
char fullmacro[80];
char varname[80];
char *oldargs[MAX_ARGS + 1] = { NULL, };
int argc, x;
int res=0;
char oldexten[256]="";
int oldpriority;
char pc[80];
char oldcontext[256] = "";
char *offsets;
int offset;
int setmacrocontext=0;
char *save_macro_exten;
char *save_macro_context;
char *save_macro_priority;
char *save_macro_offset;
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 || !strlen(macro)) {
ast_log(LOG_WARNING, "Invalid macro name specified\n");
return 0;
}
snprintf(fullmacro, sizeof(fullmacro), "macro-%s", macro);
if (!ast_exists_extension(chan, fullmacro, "s", 1, chan->callerid)) {
if (!ast_context_find(fullmacro))
ast_log(LOG_WARNING, "No such context '%s' for macro '%s'\n", fullmacro, macro);
else
ast_log(LOG_WARNING, "Context '%s' for macro '%s' lacks 's' extension, priority 1\n", fullmacro, macro);
return 0;
}
/* Save old info */
oldpriority = chan->priority;
strncpy(oldexten, chan->exten, sizeof(oldexten) - 1);
strncpy(oldcontext, chan->context, sizeof(oldcontext) - 1);
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;
setmacrocontext=1;
}
argc = 1;
/* Save old macro variables */
save_macro_exten = pbx_builtin_getvar_helper(chan, "MACRO_EXTEN");
if (save_macro_exten) save_macro_exten = strdup(save_macro_exten);
pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", oldexten);
save_macro_context = pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT");
if (save_macro_context) save_macro_context = strdup(save_macro_context);
pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", oldcontext);
save_macro_priority = pbx_builtin_getvar_helper(chan, "MACRO_PRIORITY");
if (save_macro_priority) save_macro_priority = strdup(save_macro_priority);
snprintf(pc, sizeof(pc), "%d", oldpriority);
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", pc);
save_macro_offset = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET");
if (save_macro_offset) save_macro_offset = strdup(save_macro_offset);
pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", NULL);
/* Setup environment for new run */
strcpy(chan->exten, "s");
strncpy(chan->context, fullmacro, sizeof(chan->context));
chan->priority = 1;
while((cur = strsep(&rest, "|")) && (argc < MAX_ARGS)) {
/* Save copy of old arguments if we're overwriting some, otherwise
let them pass through to the other macro */
snprintf(varname, sizeof(varname), "ARG%d", argc);
oldargs[argc] = pbx_builtin_getvar_helper(chan, varname);
if (oldargs[argc])
oldargs[argc] = strdup(oldargs[argc]);
pbx_builtin_setvar_helper(chan, varname, cur);
argc++;
}
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'))) {
/* 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;
}
switch(res) {
case AST_PBX_KEEPALIVE:
if (option_debug)
ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE in macro %s on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name);
else if (option_verbose > 1)
ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE in macro '%s' on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name);
goto out;
break;
default:
if (option_debug)
ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro);
else if (option_verbose > 1)
ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro);
goto out;
}
}
if (strcasecmp(chan->context, fullmacro)) {
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Channel '%s' jumping out of macro '%s'\n", chan->name, macro);
break;
}
/* don't stop executing extensions when we're in "h" */
if (chan->_softhangup && strcasecmp(oldexten,"h")) {
ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
chan->exten, chan->priority);
goto out;
}
chan->priority++;
}
out:
for (x=1;x<argc;x++) {
/* Restore old arguments and delete ours */
snprintf(varname, sizeof(varname), "ARG%d", x);
if (oldargs[x]) {
pbx_builtin_setvar_helper(chan, varname, oldargs[x]);
free(oldargs[x]);
} else {
pbx_builtin_setvar_helper(chan, varname, NULL);
}
}
/* Restore macro variables */
pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", save_macro_exten);
if (save_macro_exten) free(save_macro_exten);
pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", save_macro_context);
if (save_macro_context) free(save_macro_context);
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority);
if (save_macro_priority) free(save_macro_priority);
if (setmacrocontext) {
strcpy(chan->macrocontext, "");
strcpy(chan->macroexten, "");
chan->macropriority = 0;
}
if (!strcasecmp(chan->context, fullmacro)) {
/* If we're leaving the macro normally, restore original information */
chan->priority = oldpriority;
strncpy(chan->context, oldcontext, sizeof(chan->context) - 1);
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"))) {
/* Handle macro offset if it's set by checking the availability of step n + offset + 1, otherwise continue
normally if there is any problem */
if (sscanf(offsets, "%d", &offset) == 1) {
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + offset + 1, chan->callerid)) {
chan->priority += offset;
}
}
}
}
}
pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", save_macro_offset);
if (save_macro_offset) free(save_macro_offset);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, macro_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,774 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Meet me conference bridge
*
* 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/module.h>
#include <asterisk/config.h>
#include <asterisk/app.h>
#include <asterisk/musiconhold.h>
#include <asterisk/options.h>
#include <asterisk/cli.h>
#include <asterisk/say.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <linux/zaptel.h>
static char *tdesc = "Simple MeetMe conference bridge";
static char *app = "MeetMe";
static char *app2 = "MeetMeCount";
static char *synopsis = "Simple MeetMe conference bridge";
static char *synopsis2 = "MeetMe participant count";
static char *descrip =
" MeetMe(confno[|options]): Enters the user into a specified MeetMe conference.\n"
"If the conference number is omitted, the user will be prompted to enter\n"
"one. This application always returns -1. A ZAPTEL INTERFACE MUST BE INSTALLED\n"
"FOR CONFERENCING TO WORK!\n\n"
"The option string may contain zero or more of the following characters:\n"
" 'm' -- set monitor only mode (Listen only, no talking\n"
" 't' -- set talk only mode. (Talk only, no listening)\n"
" 'p' -- allow user to exit the conference by pressing '#'\n"
" 'd' -- dynamically add conference\n"
" 'v' -- video mode\n"
" 'q' -- quiet mode (don't play enter/leave sounds)\n"
" 'M' -- enable music on hold when the conference has a single caller\n"
" 'b' -- run AGI script specified in ${MEETME_AGI_BACKGROUND}\n"
" Default: conf-background.agi\n"
" (Note: This does not work with non-Zap channels in the same conference)\n"
" Not implemented yet:\n"
" 's' -- send user to admin/user menu if '*' is received\n"
" 'a' -- set admin mode\n";
static char *descrip2 =
" MeetMeCount(confno[|var]): Plays back the number of users in the specifiedi\n"
"MeetMe conference. If var is specified, playback will be skipped and the value\n"
"will be returned in the variable. Returns 0 on success or -1 on a hangup.\n"
"A ZAPTEL INTERFACE MUST BE INSTALLED FOR CONFERENCING FUNCTIONALITY.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static struct ast_conference {
char confno[AST_MAX_EXTENSION]; /* Conference */
int fd; /* Announcements fd */
int zapconf; /* Zaptel Conf # */
int users; /* Number of active users */
time_t start; /* Start time (s) */
int isdynamic; /* Created on the fly? */
char pin[AST_MAX_EXTENSION]; /* If protected by a PIN */
struct ast_conference *next;
} *confs;
static ast_mutex_t conflock = AST_MUTEX_INITIALIZER;
#include "enter.h"
#include "leave.h"
#define ENTER 0
#define LEAVE 1
#define CONF_SIZE 160
#define CONFFLAG_ADMIN (1 << 1) /* If set the user has admin access on the conference */
#define CONFFLAG_MONITOR (1 << 2) /* If set the user can only receive audio from the conference */
#define CONFFLAG_POUNDEXIT (1 << 3) /* If set asterisk will exit conference when '#' is pressed */
#define CONFFLAG_STARMENU (1 << 4) /* If set asterisk will provide a menu to the user what '*' is pressed */
#define CONFFLAG_TALKER (1 << 5) /* If set the use can only send audio to the conference */
#define CONFFLAG_QUIET (1 << 6) /* If set there will be no enter or leave sounds */
#define CONFFLAG_VIDEO (1 << 7) /* Set to enable video mode */
#define CONFFLAG_AGI (1 << 8) /* Set to run AGI Script in Background */
#define CONFFLAG_MOH (1 << 9) /* Set to have music on hold when */
static int careful_write(int fd, unsigned char *data, int len)
{
int res;
while(len) {
res = write(fd, data, len);
if (res < 1) {
if (errno != EAGAIN) {
ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno));
return -1;
} else
return 0;
}
len -= res;
data += res;
}
return 0;
}
static void conf_play(struct ast_conference *conf, int sound)
{
unsigned char *data;
int len;
ast_mutex_lock(&conflock);
switch(sound) {
case ENTER:
data = enter;
len = sizeof(enter);
break;
case LEAVE:
data = leave;
len = sizeof(leave);
break;
default:
data = NULL;
len = 0;
}
if (data)
careful_write(conf->fd, data, len);
ast_mutex_unlock(&conflock);
}
static struct ast_conference *build_conf(char *confno, char *pin, int make, int dynamic)
{
struct ast_conference *cnf;
struct zt_confinfo ztc;
ast_mutex_lock(&conflock);
cnf = confs;
while(cnf) {
if (!strcmp(confno, cnf->confno))
break;
cnf = cnf->next;
}
if (!cnf && (make || dynamic)) {
cnf = malloc(sizeof(struct ast_conference));
if (cnf) {
/* Make a new one */
memset(cnf, 0, sizeof(struct ast_conference));
strncpy(cnf->confno, confno, sizeof(cnf->confno) - 1);
strncpy(cnf->pin, pin, sizeof(cnf->pin) - 1);
cnf->fd = open("/dev/zap/pseudo", O_RDWR);
if (cnf->fd < 0) {
ast_log(LOG_WARNING, "Unable to open pseudo channel\n");
free(cnf);
cnf = NULL;
goto cnfout;
}
memset(&ztc, 0, sizeof(ztc));
/* Setup a new zap conference */
ztc.chan = 0;
ztc.confno = -1;
ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
if (ioctl(cnf->fd, ZT_SETCONF, &ztc)) {
ast_log(LOG_WARNING, "Error setting conference\n");
close(cnf->fd);
free(cnf);
cnf = NULL;
goto cnfout;
}
cnf->start = time(NULL);
cnf->zapconf = ztc.confno;
cnf->isdynamic = dynamic;
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Created ZapTel conference %d for conference '%s'\n", cnf->zapconf, cnf->confno);
cnf->next = confs;
confs = cnf;
} else
ast_log(LOG_WARNING, "Out of memory\n");
}
cnfout:
ast_mutex_unlock(&conflock);
return cnf;
}
static int confs_show(int fd, int argc, char **argv)
{
struct ast_conference *conf;
int hr, min, sec;
time_t now;
char *header_format = "%-14s %-14s %-8s %-8s\n";
char *data_format = "%-12.12s %4.4d %02d:%02d:%02d %-8s\n";
now = time(NULL);
if (argc != 2)
return RESULT_SHOWUSAGE;
conf = confs;
if (!conf) {
ast_cli(fd, "No active conferences.\n");
return RESULT_SUCCESS;
}
ast_cli(fd, header_format, "Conf Num", "Parties", "Activity", "Creation");
while(conf) {
hr = (now - conf->start) / 3600;
min = ((now - conf->start) % 3600) / 60;
sec = (now - conf->start) % 60;
if (conf->isdynamic)
ast_cli(fd, data_format, conf->confno, conf->users, hr, min, sec, "Dynamic");
else
ast_cli(fd, data_format, conf->confno, conf->users, hr, min, sec, "Static");
conf = conf->next;
}
return RESULT_SUCCESS;
}
static char show_confs_usage[] =
"Usage: show conferences\n"
" Provides summary information on conferences with active\n"
" participation.\n";
static struct ast_cli_entry cli_show_confs = {
{ "show", "conferences", NULL }, confs_show,
"Show status of conferences", show_confs_usage, NULL };
static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int confflags)
{
struct ast_conference *prev=NULL, *cur;
int fd;
struct zt_confinfo ztc;
struct ast_frame *f;
struct ast_channel *c;
struct ast_frame fr;
int outfd;
int ms;
int nfds;
int res;
int flags;
int retryzap;
int origfd;
int musiconhold = 0;
int firstpass = 0;
int ret = -1;
int x;
struct ast_app *app;
char *agifile;
char *agifiledefault = "conf-background.agi";
ZT_BUFFERINFO bi;
char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
char *buf = __buf + AST_FRIENDLY_OFFSET;
conf->users++;
if (!(confflags & CONFFLAG_QUIET) && conf->users == 1) {
if (!ast_streamfile(chan, "conf-onlyperson", chan->language))
ast_waitstream(chan, "");
}
if (confflags & CONFFLAG_VIDEO) {
/* Set it into linear mode (write) */
if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", chan->name);
goto outrun;
}
/* Set it into linear mode (read) */
if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) {
ast_log(LOG_WARNING, "Unable to set '%s' to read linear mode\n", chan->name);
goto outrun;
}
} else {
/* Set it into U-law mode (write) */
if (ast_set_write_format(chan, AST_FORMAT_ULAW) < 0) {
ast_log(LOG_WARNING, "Unable to set '%s' to write ulaw mode\n", chan->name);
goto outrun;
}
/* Set it into U-law mode (read) */
if (ast_set_read_format(chan, AST_FORMAT_ULAW) < 0) {
ast_log(LOG_WARNING, "Unable to set '%s' to read ulaw mode\n", chan->name);
goto outrun;
}
}
ast_indicate(chan, -1);
retryzap = strcasecmp(chan->type, "Zap");
zapretry:
origfd = chan->fds[0];
if (retryzap) {
fd = open("/dev/zap/pseudo", O_RDWR);
if (fd < 0) {
ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
goto outrun;
}
/* Make non-blocking */
flags = fcntl(fd, F_GETFL);
if (flags < 0) {
ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno));
close(fd);
goto outrun;
}
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno));
close(fd);
goto outrun;
}
/* Setup buffering information */
memset(&bi, 0, sizeof(bi));
bi.bufsize = CONF_SIZE;
bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
bi.numbufs = 4;
if (ioctl(fd, ZT_SET_BUFINFO, &bi)) {
ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno));
close(fd);
goto outrun;
}
if (confflags & CONFFLAG_VIDEO) {
x = 1;
if (ioctl(fd, ZT_SETLINEAR, &x)) {
ast_log(LOG_WARNING, "Unable to set linear mode: %s\n", strerror(errno));
close(fd);
goto outrun;
}
}
nfds = 1;
} else {
/* XXX Make sure we're not running on a pseudo channel XXX */
fd = chan->fds[0];
nfds = 0;
}
memset(&ztc, 0, sizeof(ztc));
/* Check to see if we're in a conference... */
ztc.chan = 0;
if (ioctl(fd, ZT_GETCONF, &ztc)) {
ast_log(LOG_WARNING, "Error getting conference\n");
close(fd);
goto outrun;
}
if (ztc.confmode) {
/* Whoa, already in a conference... Retry... */
if (!retryzap) {
ast_log(LOG_DEBUG, "Zap channel is in a conference already, retrying with pseudo\n");
retryzap = 1;
goto zapretry;
}
}
memset(&ztc, 0, sizeof(ztc));
/* Add us to the conference */
ztc.chan = 0;
ztc.confno = conf->zapconf;
if (confflags & CONFFLAG_MONITOR)
ztc.confmode = ZT_CONF_CONFMON | ZT_CONF_LISTENER;
else if (confflags & CONFFLAG_TALKER)
ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER;
else
ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
if (ioctl(fd, ZT_SETCONF, &ztc)) {
ast_log(LOG_WARNING, "Error setting conference\n");
close(fd);
goto outrun;
}
ast_log(LOG_DEBUG, "Placed channel %s in ZAP conf %d\n", chan->name, conf->zapconf);
if (!firstpass && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) {
firstpass = 1;
if (!(confflags & CONFFLAG_QUIET))
conf_play(conf, ENTER);
}
if (confflags & CONFFLAG_AGI) {
/* Get name of AGI file to run from $(MEETME_AGI_BACKGROUND)
or use default filename of conf-background.agi */
agifile = pbx_builtin_getvar_helper(chan,"MEETME_AGI_BACKGROUND");
if (!agifile)
agifile = agifiledefault;
if (!strcasecmp(chan->type,"Zap")) {
/* Set CONFMUTE mode on Zap channel to mute DTMF tones */
x = 1;
ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
}
/* Find a pointer to the agi app and execute the script */
app = pbx_findapp("agi");
if (app) {
ret = pbx_exec(chan, app, agifile, 1);
} else {
ast_log(LOG_WARNING, "Could not find application (agi)\n");
ret = -2;
}
if (!strcasecmp(chan->type,"Zap")) {
/* Remove CONFMUTE mode on Zap channel */
x = 0;
ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
}
} else for(;;) {
outfd = -1;
ms = -1;
c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms);
/* trying to add moh for single person conf */
if (confflags & CONFFLAG_MOH) {
if (conf->users == 1) {
if (musiconhold == 0) {
ast_moh_start(chan, NULL);
musiconhold = 1;
}
} else {
if (musiconhold) {
ast_moh_stop(chan);
musiconhold = 0;
}
}
}
/* end modifications */
if (c) {
if (c->fds[0] != origfd) {
if (retryzap) {
/* Kill old pseudo */
close(fd);
}
ast_log(LOG_DEBUG, "Ooh, something swapped out under us, starting over\n");
retryzap = 0;
goto zapretry;
}
f = ast_read(c);
if (!f)
break;
if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#') && (confflags & CONFFLAG_POUNDEXIT)) {
ret = 0;
break;
} else if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*') && (confflags & CONFFLAG_STARMENU)) {
if ((confflags & CONFFLAG_ADMIN)) {
/* Do admin stuff here */
} else {
/* Do user menu here */
}
} 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);
} else
ast_log(LOG_WARNING, "Huh? Got a non-ulaw (%d) frame in the conference\n", f->subclass);
}
}
ast_frfree(f);
} else if (outfd > -1) {
res = read(outfd, buf, CONF_SIZE);
if (res > 0) {
memset(&fr, 0, sizeof(fr));
fr.frametype = AST_FRAME_VOICE;
fr.subclass = AST_FORMAT_ULAW;
fr.datalen = res;
fr.samples = res;
fr.data = buf;
fr.offset = AST_FRIENDLY_OFFSET;
if (ast_write(chan, &fr) < 0) {
ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno));
/* break; */
}
} else
ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno));
}
}
if (fd != chan->fds[0])
close(fd);
else {
/* Take out of conference */
/* Add us to the conference */
ztc.chan = 0;
ztc.confno = 0;
ztc.confmode = 0;
if (ioctl(fd, ZT_SETCONF, &ztc)) {
ast_log(LOG_WARNING, "Error setting conference\n");
}
}
if (!(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN))
conf_play(conf, LEAVE);
outrun:
ast_mutex_lock(&conflock);
/* Clean up */
conf->users--;
if (!conf->users) {
/* No more users -- close this one out */
cur = confs;
while(cur) {
if (cur == conf) {
if (prev)
prev->next = conf->next;
else
confs = conf->next;
break;
}
prev = cur;
cur = cur->next;
}
if (!cur)
ast_log(LOG_WARNING, "Conference not found\n");
close(conf->fd);
free(conf);
}
ast_mutex_unlock(&conflock);
return ret;
}
static struct ast_conference *find_conf(char *confno, int make, int dynamic)
{
struct ast_config *cfg;
struct ast_variable *var;
struct ast_conference *cnf = confs;
/* Check first in the conference list */
ast_mutex_lock(&conflock);
while (cnf) {
if (!strcmp(confno, cnf->confno))
break;
cnf = cnf->next;
}
ast_mutex_unlock(&conflock);
if (!cnf) {
if (dynamic) {
/* No need to parse meetme.conf */
ast_log(LOG_DEBUG, "Using dynamic conference '%s'\n", confno);
cnf = build_conf(confno, "", make, dynamic);
} else {
/* Check the config */
cfg = ast_load("meetme.conf");
if (!cfg) {
ast_log(LOG_WARNING, "No meetme.conf file :(\n");
return NULL;
}
var = ast_variable_browse(cfg, "rooms");
while(var) {
if (!strcasecmp(var->name, "conf")) {
/* Separate the PIN */
char *pin, *conf;
if ((pin = ast_strdupa(var->value))) {
conf = strsep(&pin, "|,");
if (!strcasecmp(conf, confno)) {
/* Bingo it's a valid conference */
if (pin)
cnf = build_conf(confno, pin, make, dynamic);
else
cnf = build_conf(confno, "", make, dynamic);
break;
}
}
}
var = var->next;
}
if (!var) {
ast_log(LOG_DEBUG, "%s isn't a valid conference\n", confno);
}
ast_destroy(cfg);
}
}
return cnf;
}
static int count_exec(struct ast_channel *chan, void *data)
{
struct localuser *u;
int res = 0;
struct ast_conference *conf;
int count;
char *confnum, *localdata;
char val[80] = "0";
if (!data || !strlen(data)) {
ast_log(LOG_WARNING, "MeetMeCount requires an argument (conference number)\n");
return -1;
}
localdata = ast_strdupa(data);
LOCAL_USER_ADD(u);
confnum = strsep(&localdata,"|");
conf = find_conf(confnum, 0, 0);
if (conf)
count = conf->users;
else
count = 0;
if (localdata && strlen(localdata)){
/* have var so load it and exit */
snprintf(val,sizeof(val), "%i",count);
pbx_builtin_setvar_helper(chan, localdata,val);
} else {
if (chan->_state != AST_STATE_UP)
ast_answer(chan);
res = ast_say_number(chan, count, "", chan->language);
}
LOCAL_USER_REMOVE(u);
return res;
}
static int conf_exec(struct ast_channel *chan, void *data)
{
int res=-1;
struct localuser *u;
char confno[AST_MAX_EXTENSION] = "";
int allowretry = 0;
int retrycnt = 0;
struct ast_conference *cnf;
int confflags = 0;
int dynamic = 0;
char *notdata, *info, *inflags = NULL, *inpin = NULL;
if (!data || !strlen(data)) {
allowretry = 1;
notdata = "";
} else {
notdata = data;
}
LOCAL_USER_ADD(u);
if (chan->_state != AST_STATE_UP)
ast_answer(chan);
info = ast_strdupa((char *)notdata);
if (info) {
char *tmp = strsep(&info, "|");
strncpy(confno, tmp, sizeof(confno));
if (strlen(confno) == 0) {
allowretry = 1;
}
}
if (info)
inflags = strsep(&info, "|");
if (info)
inpin = strsep(&info, "|");
if (inflags) {
if (strchr(inflags, 'a'))
confflags |= CONFFLAG_ADMIN;
if (strchr(inflags, 'm'))
confflags |= CONFFLAG_MONITOR;
if (strchr(inflags, 'p'))
confflags |= CONFFLAG_POUNDEXIT;
if (strchr(inflags, 's'))
confflags |= CONFFLAG_STARMENU;
if (strchr(inflags, 't'))
confflags |= CONFFLAG_TALKER;
if (strchr(inflags, 'q'))
confflags |= CONFFLAG_QUIET;
if (strchr(inflags, 'M'))
confflags |= CONFFLAG_MOH;
if (strchr(inflags, 'b'))
confflags |= CONFFLAG_AGI;
if (strchr(inflags, 'd'))
dynamic = 1;
}
do {
if (retrycnt > 3)
allowretry = 0;
while (allowretry && (!strlen(confno)) && (++retrycnt < 4)) {
/* Prompt user for conference number */
res = ast_app_getdata(chan, "conf-getconfno", confno, sizeof(confno) - 1, 0);
if (res < 0) {
/* Don't try to validate when we catch an error */
strcpy(confno, "");
allowretry = 0;
break;
}
}
if (strlen(confno)) {
/* Check the validity of the conference */
cnf = find_conf(confno, 1, dynamic);
if (!cnf) {
res = ast_streamfile(chan, "conf-invalid", chan->language);
if (!res)
ast_waitstream(chan, "");
res = -1;
if (allowretry)
strcpy(confno, "");
} else {
if (strlen(cnf->pin)) {
char pin[AST_MAX_EXTENSION];
if (inpin && *inpin) {
strncpy(pin, inpin, sizeof(pin) - 1);
} else {
/* Prompt user for pin if pin is required */
res = ast_app_getdata(chan, "conf-getpin", pin, sizeof(pin) - 1, 0);
}
if (res >= 0) {
if (!strcasecmp(pin, cnf->pin)) {
/* Pin correct */
allowretry = 0;
/* Run the conference */
res = conf_run(chan, cnf, confflags);
} else {
/* Pin invalid */
res = ast_streamfile(chan, "conf-invalidpin", chan->language);
if (!res)
ast_waitstream(chan, "");
res = -1;
if (allowretry)
strcpy(confno, "");
}
} else {
res = -1;
allowretry = 0;
}
} else {
/* No pin required */
allowretry = 0;
/* Run the conference */
res = conf_run(chan, cnf, confflags);
}
}
}
} while (allowretry);
/* Do the conference */
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
ast_cli_unregister(&cli_show_confs);
ast_unregister_application(app2);
return ast_unregister_application(app);
}
int load_module(void)
{
ast_cli_register(&cli_show_confs);
ast_register_application(app2, count_exec, synopsis2, descrip2);
return ast_register_application(app, conf_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,148 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Digital Milliwatt Test
*
* Copyright (C) 2002, 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/module.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
static char *tdesc = "Digital Milliwatt (mu-law) Test Application";
static char *app = "Milliwatt";
static char *synopsis = "Generate a Constant 1000Hz tone at 0dbm (mu-law)";
static char *descrip =
"Milliwatt(): Generate a Constant 1000Hz tone at 0dbm (mu-law)\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static char digital_milliwatt[] = {0x1e,0x0b,0x0b,0x1e,0x9e,0x8b,0x8b,0x9e} ;
static void *milliwatt_alloc(struct ast_channel *chan, void *params)
{
int *indexp;
indexp = malloc(sizeof(int));
if (indexp == NULL) return(NULL);
*indexp = 0;
return(indexp);
}
static void milliwatt_release(struct ast_channel *chan, void *data)
{
free(data);
return;
}
static int milliwatt_generate(struct ast_channel *chan, void *data, int len, int samples)
{
struct ast_frame wf;
unsigned char waste[AST_FRIENDLY_OFFSET];
unsigned char buf[640];
int i,*indexp = (int *) data;
if (len > sizeof(buf))
{
ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",sizeof(buf),len);
len = sizeof(buf);
}
waste[0] = 0; /* make compiler happy */
wf.frametype = AST_FRAME_VOICE;
wf.subclass = AST_FORMAT_ULAW;
wf.offset = AST_FRIENDLY_OFFSET;
wf.mallocd = 0;
wf.data = buf;
wf.datalen = len;
wf.samples = wf.datalen;
wf.src = "app_milliwatt";
/* create a buffer containing the digital milliwatt pattern */
for(i = 0; i < len; i++)
{
buf[i] = digital_milliwatt[(*indexp)++];
*indexp &= 7;
}
if (ast_write(chan,&wf) < 0)
{
ast_log(LOG_WARNING,"Failed to write frame to '%s': %s\n",chan->name,strerror(errno));
return -1;
}
return 0;
}
static struct ast_generator milliwattgen =
{
alloc: milliwatt_alloc,
release: milliwatt_release,
generate: milliwatt_generate,
} ;
static int milliwatt_exec(struct ast_channel *chan, void *data)
{
struct localuser *u;
LOCAL_USER_ADD(u);
ast_set_write_format(chan, AST_FORMAT_ULAW);
ast_set_read_format(chan, AST_FORMAT_ULAW);
if (chan->_state != AST_STATE_UP)
{
ast_answer(chan);
}
if (ast_activate_generator(chan,&milliwattgen,"milliwatt") < 0)
{
ast_log(LOG_WARNING,"Failed to activate generator on '%s'\n",chan->name);
return -1;
}
while(!ast_safe_sleep(chan, 10000));
ast_deactivate_generator(chan);
LOCAL_USER_REMOVE(u);
return -1;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, milliwatt_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -11,7 +11,6 @@
* the GNU General Public License
*/
#include <asterisk/lock.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
@@ -28,7 +27,6 @@
#include <pthread.h>
#include <sys/time.h>
#define LOCAL_MPG_123 "/usr/local/bin/mpg123"
#define MPG_123 "/usr/bin/mpg123"
static char *tdesc = "Silly MP3 Application";
@@ -61,56 +59,33 @@ static int mp3play(char *filename, int fd)
close(x);
}
/* Execute mpg123, but buffer if it's a net connection */
if (strncmp(filename, "http://", 7)) {
/* Most commonly installed in /usr/local/bin */
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", "--mono", "-r", "8000", filename, (char *)NULL);
/* As a last-ditch effort, try to use PATH */
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", "--mono", "-r", "8000", filename, (char *)NULL);
/* But many places has it in /usr/bin */
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", "--mono", "-r", "8000", filename, (char *)NULL);
}
if (strncmp(filename, "http://", 7))
execl(MPG_123, MPG_123, "-q", "-s", "-b", "1024", "--mono", "-r", "8000", filename, NULL);
else
execl(MPG_123, MPG_123, "-q", "-s", "--mono", "-r", "8000", filename, NULL);
ast_log(LOG_WARNING, "Execute of mpg123 failed\n");
return -1;
}
static int timed_read(int fd, void *data, int datalen)
{
int res;
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, "Selected timed out/errored out with %d\n", res);
return -1;
}
return read(fd, data, datalen);
}
static int mp3_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
int fds[2];
int rfds[1 + AST_MAX_FDS];
int ms = -1;
int pid = -1;
int us;
int exception;
int owriteformat;
struct timeval tv;
struct timeval last;
struct ast_frame *f;
int x;
struct myframe {
struct ast_frame f;
char offset[AST_FRIENDLY_OFFSET];
short frdata[160];
char frdata[160];
} myf;
last.tv_usec = 0;
last.tv_sec = 0;
@@ -133,20 +108,29 @@ static int mp3_exec(struct ast_channel *chan, void *data)
}
res = mp3play((char *)data, fds[1]);
/* Wait 1000 ms first */
ms = 1000;
if (res >= 0) {
pid = res;
/* Order is important -- there's almost always going to be mp3... we want to prioritize the
user */
rfds[AST_MAX_FDS] = fds[0];
for (;;) {
ms = ast_waitfor(chan, ms);
if (ms < 0) {
CHECK_BLOCKING(chan);
for (x=0;x<AST_MAX_FDS;x++)
rfds[x] = chan->fds[x];
res = ast_waitfor_n_fd(rfds, AST_MAX_FDS+1, &ms, &exception);
chan->blocking = 0;
if (res < 1) {
ast_log(LOG_DEBUG, "Hangup detected\n");
res = -1;
break;
}
if (ms) {
for(x=0;x<AST_MAX_FDS;x++)
if (res == chan->fds[x])
break;
if (x < AST_MAX_FDS) {
if (exception)
chan->exception = 1;
f = ast_read(chan);
if (!f) {
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
@@ -160,13 +144,26 @@ static int mp3_exec(struct ast_channel *chan, void *data)
break;
}
ast_frfree(f);
} else {
res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata));
} else if (res == fds[0]) {
gettimeofday(&tv, NULL);
if (last.tv_sec || last.tv_usec) {
/* We should wait at least a frame length */
us = sizeof(myf.frdata) / 16 * 1000;
/* Subtract 1,000,000 us for each second late we've passed */
us -= (tv.tv_sec - last.tv_sec) * 1000000;
/* And one for each us late we've passed */
us -= (tv.tv_usec - last.tv_usec);
/* Sleep that long if needed */
if (us > 0)
usleep(us);
}
last = tv;
res = 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.timelen = res / 16;
myf.f.mallocd = 0;
myf.f.offset = AST_FRIENDLY_OFFSET;
myf.f.src = __PRETTY_FUNCTION__;
@@ -178,9 +175,11 @@ static int mp3_exec(struct ast_channel *chan, void *data)
} else {
ast_log(LOG_DEBUG, "No more mp3\n");
res = 0;
break;
}
ms = res / 16;
} else {
ast_log(LOG_DEBUG, "HuhHHH?\n");
res = -1;
break;
}
}
}

View File

@@ -1,253 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* ParkAndAnnounce application for Asterisk
* Author: Ben Miller <bgmiller@dccinc.com>
* With TONS of help from Mark!
*
* Asterisk is Copyrighted as follows
* 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 <sys/types.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/parking.h>
#include <asterisk/options.h>
#include <asterisk/logger.h>
#include <asterisk/say.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";
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 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"
"return_context: the goto style label to jump the call back into after timeout. default=prio+1\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int parkandannounce_exec(struct ast_channel *chan, void *data)
{
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 localuser *u;
if (!data) {
ast_log(LOG_WARNING, "Park requires an argument (parkinglot)\n");
return -1;
}
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;
}
timeout = atoi(strsep(&s, "|"));
timeout *= 1000;
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 */
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");
}
}
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. */
ast_masq_park_call(chan, NULL, timeout, &lot);
res=-1;
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 */
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;
}
ast_stopstream(dchan);
/* now we have the call placed and are ready to play stuff to it */
ast_verbose(VERBOSE_PREFIX_4 "Announce Template:%s\n", template);
tpl_working = template;
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;
}
}
}
ast_stopstream(dchan);
ast_hangup(dchan);
LOCAL_USER_REMOVE(u);
free(orig_s);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
/* return ast_register_application(app, park_exec); */
return ast_register_application(app, parkandannounce_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -11,7 +11,6 @@
* the GNU General Public License
*/
#include <asterisk/lock.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
@@ -33,11 +32,9 @@ static char *descrip =
"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";
"hasn't been answered yet. If 'skip' is not specified, the channel will be\n"
"answered before the sound is played. Returns -1 if the channel was hung up,\n"
"or if the file does not exist. Returns 0 otherwise.\n";
STANDARD_LOCAL_USER;
@@ -50,28 +47,23 @@ static int playback_exec(struct ast_channel *chan, void *data)
char tmp[256];
char *options;
int option_skip=0;
int option_noanswer = 0;
char *stringp;
if (!data || !strlen((char *)data)) {
ast_log(LOG_WARNING, "Playback requires an argument (filename)\n");
return -1;
}
strncpy(tmp, (char *)data, sizeof(tmp)-1);
stringp=tmp;
strsep(&stringp, "|");
options = strsep(&stringp, "|");
strncpy(tmp, (char *)data, sizeof(tmp));
strtok(tmp, "|");
options = strtok(NULL, "|");
if (options && !strcasecmp(options, "skip"))
option_skip = 1;
if (options && !strcasecmp(options, "noanswer"))
option_noanswer = 1;
LOCAL_USER_ADD(u);
if (chan->_state != AST_STATE_UP) {
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 send this while on-hook */
} else
/* Otherwise answer */
res = ast_answer(chan);
}
if (!res) {
@@ -79,10 +71,8 @@ static int playback_exec(struct ast_channel *chan, void *data)
res = ast_streamfile(chan, tmp, chan->language);
if (!res)
res = ast_waitstream(chan, "");
else {
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
res = 0;
}
ast_stopstream(chan);
}
LOCAL_USER_REMOVE(u);

View File

@@ -1,171 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Block all calls without Caller*ID, require phone # to be entered
*
* 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/options.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/translate.h>
#include <asterisk/image.h>
#include <asterisk/callerid.h>
#include <asterisk/app.h>
#include <asterisk/config.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#define PRIV_CONFIG "privacy.conf"
static char *tdesc = "Require phone number to be entered, if no CallerID sent";
static char *app = "PrivacyManager";
static char *synopsis = "Require phone number to be entered, if no CallerID sent";
static char *descrip =
" PrivacyManager: If no Caller*ID is sent, PrivacyManager answers the\n"
"channel and asks the caller to enter their 10 digit phone number.\n"
"The caller is given 3 attempts. If after 3 attempts, they do not enter\n"
"their 10 digit phone number, and if there exists a priority n + 101,\n"
"where 'n' is the priority of the current instance, then the\n"
"channel will be setup to continue at that priority level.\n"
"Otherwise, it returns 0. Does nothing if Caller*ID was received on the\n"
"channel.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int
privacy_exec (struct ast_channel *chan, void *data)
{
int res=0;
int retries;
int maxretries = 3;
int x;
char *s;
char phone[10];
char new_cid[144];
struct localuser *u;
struct ast_config *cfg;
LOCAL_USER_ADD (u);
if (chan->callerid)
{
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3 "CallerID Present: Skipping\n");
}
else
{
/*Answer the channel if it is not already*/
if (chan->_state != AST_STATE_UP) {
res = ast_answer(chan);
if (res) {
LOCAL_USER_REMOVE(u);
return -1;
}
}
/*Read in the config file*/
cfg = ast_load(PRIV_CONFIG);
/*Play unidentified call*/
res = ast_safe_sleep(chan, 1000);
if (!res)
res = ast_streamfile(chan, "privacy-unident", chan->language);
if (!res)
res = ast_waitstream(chan, "");
if (cfg && (s = ast_variable_retrieve(cfg, "general", "maxretries"))) {
if (sscanf(s, "%d", &x) == 1) {
maxretries = x;
} else {
ast_log(LOG_WARNING, "Invalid max retries argument\n");
}
}
/*Ask for 10 digit number, give 3 attempts*/
for (retries = 0; retries < maxretries; retries++) {
if (!res)
res = ast_app_getdata(chan, "privacy-prompt", phone, sizeof(phone), 0);
if (res < 0)
break;
/*Make sure we get 10 digits*/
if (strlen(phone) == 10)
break;
else {
res = ast_streamfile(chan, "privacy-incorrect", chan->language);
if (!res)
res = ast_waitstream(chan, "");
}
}
/*Got a number, play sounds and send them on their way*/
if ((retries < maxretries) && !res) {
res = ast_streamfile(chan, "privacy-thankyou", chan->language);
if (!res)
res = ast_waitstream(chan, "");
snprintf (new_cid, sizeof (new_cid), "\"%s\" <%s>", "Privacy Manager", phone);
ast_set_callerid (chan, new_cid, 0);
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID to %s\n",new_cid);
} else {
/*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;
}
if (cfg)
ast_destroy(cfg);
}
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, privacy_exec, synopsis,
descrip);
}
char *
description (void)
{
return tdesc;
}
int
usecount (void)
{
int res;
STANDARD_USECOUNT (res);
return res;
}
char *
key ()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,386 +0,0 @@
/** @file app_qcall.c
*
* Asterisk -- A telephony toolkit for Linux.
*
* Call back a party and connect them to a running pbx thread
*
* 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
*
* Call a user from a file contained within a queue (/var/spool/asterisk/qcall)
*
* The queue is a directory containing files with the call request information
* as a single line of text as follows:
*
* Dialstring Caller-ID Extension Maxsecs [Identifier] [Required-response]
*
* Dialstring -- A Dial String (The number to be called) in the
* format Technology/Number, such IAX/mysys/1234 or Zap/g1/1234
*
* Caller-ID -- A Standard nomalized representation of the Caller-ID of
* the number being dialed (generally 10 digits in the US). Leave as
* "asreceived" to use the default Caller*ID
*
* Extension -- The Extension (optionally Extension@context) that the
* user should be "transferred" to after acceptance of the call.
*
* Maxsecs -- The Maximum time of the call in seconds. Specify 0 for infinite.
*
* Identifier -- The "Identifier" of the request. This is used to determine
* the names of the audio prompt files played. The first prompt, the one that
* asks for the input, is just the exact string specified as the identifier.
* The second prompt, the one that is played after the correct input is given,
* (generally a "thank you" recording), is the specified string with "-ok"
* added to the end. So, if you specify "foo" as the identifier, your first
* prompt file that will be played will be "foo" and the second one will be
* "foo-ok". If omitted no prompt is given
*
* Required-Response (Optional) -- Specify a digit string to be used as the
* acceptance "code" if you desire it to be something other then "1". This
* can be used to implement some sort of PIN or security system. It may be
* more then a single character.
*
* NOTE: It is important to remember that the process that creates these
* files needs keep and maintain a write lock (using flock with the LOCK_EX
* option) when writing these files.
*
*/
#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/options.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <dirent.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/file.h>
#include "../astconf.h"
static char qdir[255];
static char *tdesc = "Call from Queue";
static pthread_t qcall_thread;
static int debug = 0;
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
#define OLDESTOK 14400 /* not any more then this number of secs old */
#define INITIALONE 1 /* initial wait before the first one in secs */
#define NEXTONE 600 /* wait before trying it again in secs */
#define MAXWAITFORANSWER 45000 /* max call time before answer */
/* define either one or both of these two if your application requires it */
#if 0
#define ACCTCODE "SOMETHING" /* Account code */
#define AMAFLAGS AST_CDR_BILLING /* AMA flags */
#endif
/* define this if you want to have a particular CLID display on the user's
phone when they receive the call */
#if 0
#define OURCLID "2564286275" /* The callerid to be displayed when calling */
#endif
static void *qcall_do(void *arg);
static void *qcall(void *ignore)
{
pthread_t dialer_thread;
DIR *dirp;
FILE *fp;
struct dirent *dp;
char fname[80];
struct stat mystat;
time_t t;
void *arg;
pthread_attr_t attr;
time(&t);
if (debug) printf("@@@@ qcall starting at %s",ctime(&t));
for(;;)
{
time(&t);
dirp = opendir(qdir);
if (!dirp)
{
perror("app_qcall:Cannot open queue directory");
break;
}
while((dp = readdir(dirp)) != NULL)
{
if (dp->d_name[0] == '.') continue;
sprintf(fname,"%s/%s",qdir,dp->d_name);
if (stat(fname,&mystat) == -1)
{
perror("app_qcall:stat");
fprintf(stderr,"%s\n",fname);
continue;
}
/* if not a regular file, skip it */
if ((mystat.st_mode & S_IFMT) != S_IFREG) continue;
/* if not yet .... */
if (mystat.st_atime == mystat.st_mtime)
{ /* first time */
if ((mystat.st_atime + INITIALONE) > t)
continue;
}
else
{ /* already looked at once */
if ((mystat.st_atime + NEXTONE) > t) continue;
}
/* if too old */
if (mystat.st_mtime < (t - OLDESTOK))
{
/* kill it, its too old */
unlink(fname);
continue;
}
/* "touch" file's access time */
fp = fopen(fname,"r");
if (fp) fclose(fp);
/* make a copy of the filename string, so that we
may go on and use the buffer */
arg = (void *) strdup(fname);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (pthread_create(&dialer_thread,&attr,qcall_do,arg) == -1)
{
perror("qcall: Cannot create thread");
continue;
}
}
closedir(dirp);
sleep(1);
}
pthread_exit(NULL);
}
/* single thread with one file (request) to dial */
static void *qcall_do(void *arg)
{
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 */
strcpy(fname,(char *)arg);
free(arg);
time(&t);
fp = fopen(fname,"r");
if (!fp) /* if cannot open request file */
{
perror("qcall_do:fopen");
fprintf(stderr,"%s\n",fname);
unlink(fname);
pthread_exit(NULL);
}
/* lock the file */
if (flock(fileno(fp),LOCK_EX) == -1)
{
perror("qcall_do:flock");
fprintf(stderr,"%s\n",fname);
pthread_exit(NULL);
}
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)
{
fprintf(stderr,"qcall_do:file line invalid in file %s:\n",fname);
pthread_exit(NULL);
}
flock(fileno(fp),LOCK_UN);
fclose(fp);
tele = strchr(dialstr,'/');
if (!tele)
{
fprintf(stderr,"qcall_do:Dial number must be in format tech/number\n");
unlink(fname);
pthread_exit(NULL);
}
*tele++ = 0;
channel = ast_request(dialstr,AST_FORMAT_SLINEAR,tele);
if (channel)
{
ast_set_read_format(channel,AST_FORMAT_SLINEAR);
ast_set_write_format(channel,AST_FORMAT_SLINEAR);
#ifdef OURCLID
if (channel->callerid)
free(channel->callerid);
channel->callerid = strdup(OURCLID);
if (channel->ani)
free(channel->ani);
channel->ani = strdup(OURCLID);
#endif
channel->whentohangup = 0;
channel->appl = "AppQcall";
channel->data = "(Outgoing Line)";
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Qcall initiating call to %s/%s on %s (%s)\n",
dialstr,tele,channel->name,fname);
ast_call(channel,tele,MAXWAITFORANSWER);
}
else
{
fprintf(stderr,"qcall_do:Sorry unable to obtain channel\n");
pthread_exit(NULL);
}
if (strcasecmp(clid, "asreceived")) {
if (channel->callerid) free(channel->callerid);
channel->callerid = NULL;
if (channel->ani) free(channel->ani);
channel->ani = NULL;
}
if (channel->_state == AST_STATE_UP)
if (debug) printf("@@@@ Autodial:Line is Up\n");
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Qcall waiting for answer on %s\n",
channel->name);
while(ms > 0){
struct ast_frame *f;
ms = ast_waitfor(channel,ms);
f = ast_read(channel);
if (!f)
{
if (debug) printf("@@@@ qcall_do:Hung Up\n");
unlink(fname);
break;
}
if (f->frametype == AST_FRAME_CONTROL)
{
if (f->subclass == AST_CONTROL_HANGUP)
{
if (debug) printf("@@@@ qcall_do:Hung Up\n");
unlink(fname);
ast_frfree(f);
break;
}
if (f->subclass == AST_CONTROL_ANSWER)
{
if (debug) printf("@@@@ qcall_do:Phone Answered\n");
if (channel->_state == AST_STATE_UP)
{
unlink(fname);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Qcall got answer on %s\n",
channel->name);
usleep(1500000);
if (strlen(ident)) {
ast_streamfile(channel,ident,0);
if (ast_readstring(channel,buf,strlen(reqinp),10000,5000,"#"))
{
ast_stopstream(channel);
if (debug) printf("@@@@ qcall_do: timeout or hangup in dtmf read\n");
ast_frfree(f);
break;
}
ast_stopstream(channel);
if (strcmp(buf,reqinp)) /* if not match */
{
if (debug) printf("@@@@ qcall_do: response (%s) does not match required (%s)\n",buf,reqinp);
ast_frfree(f);
break;
}
ast_frfree(f);
}
/* okay, now we go for it */
context = strchr(extstr,'@');
if (!context) context = "default";
else *context++ = 0;
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Qcall got accept, now putting through to %s@%s on %s\n",
extstr,context,channel->name);
if (strlen(ident)) {
strcat(ident,"-ok");
/* if file existant, play it */
if (!ast_streamfile(channel,ident,0))
{
ast_waitstream(channel,"");
ast_stopstream(channel);
}
}
if (strcasecmp(clid, "asreceived")) {
channel->callerid = strdup(clid);
channel->ani = strdup(clid);
}
channel->language[0] = 0;
channel->dnid = strdup(extstr);
#ifdef AMAFLAGS
channel->amaflags = AMAFLAGS;
#endif
#ifdef ACCTCODE
strcpy(channel->accountcode,ACCTCODE);
#else
channel->accountcode[0] = 0;
#endif
if (maxsecs) /* if finite length call */
{
time(&channel->whentohangup);
channel->whentohangup += maxsecs;
}
strcpy(channel->exten,extstr);
strcpy(channel->context,context);
channel->priority = 1;
printf("Caller ID is %s\n", channel->callerid);
ast_pbx_run(channel);
pthread_exit(NULL);
}
}
else if(f->subclass==AST_CONTROL_RINGING)
if (debug) printf("@@@@ qcall_do:Phone Ringing end\n");
}
ast_frfree(f);
}
ast_hangup(channel);
if (debug) printf("@@@@ qcall_do:Hung up channel\n");
pthread_exit(NULL);
return NULL;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return 0;
}
int load_module(void)
{
snprintf((char *)qdir,sizeof(qdir)-1,"%s/%s",(char *)ast_config_AST_SPOOL_DIR,"qcall");
mkdir(qdir,0760);
pthread_create(&qcall_thread,NULL,qcall,NULL);
return 0;
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,128 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Random application
*
* Copyright (c) 2003-2004 Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <asterisk__app_random__20040111@the-tilghman.com>
*
* This code is released by the author with no restrictions on usage or distribution.
*
*/
#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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
static char *tdesc = "Random goto";
static char *app_random = "Random";
static char *random_synopsis = "Conditionally branches, based upon a probability";
static char *random_descrip =
"Random([probability]:[[context|]extension|]priority)\n"
" probability := INTEGER in the range 1 to 100\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int random_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char *s, *ts;
char *exten, *pri, *context;
char *prob;
int probint, priorityint;
if (!data) {
ast_log(LOG_WARNING, "Random requires an argument ([probability]:[[context|]extension|]priority)\n");
return -1;
}
LOCAL_USER_ADD(u);
s = ast_strdupa((void *) data);
prob = strsep(&ts,":");
if ((!prob) || (sscanf(prob, "%d", &probint) != 1))
probint = 0;
if ((random() % 100) + probint > 100) {
context = strsep(&s, "|");
exten = strsep(&s, "|");
if (!exten) {
/* Only a priority */
pri = context;
exten = NULL;
context = NULL;
} else {
pri = strsep(&s, "|");
if (!pri) {
pri = exten;
exten = context;
context = NULL;
}
}
if (!pri) {
ast_log(LOG_WARNING, "No label specified\n");
LOCAL_USER_REMOVE(u);
return -1;
} else if (sscanf(pri, "%d", &priorityint) != 1) {
ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", pri);
LOCAL_USER_REMOVE(u);
return -1;
}
/* At this point we have a priority and */
/* maybe an extension and a context */
chan->priority = priorityint - 1;
if (exten && strcasecmp(exten, "BYEXTENSION"))
strncpy(chan->exten, exten, sizeof(chan->exten)-1);
if (context)
strncpy(chan->context, context, sizeof(chan->context)-1);
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "Random branches to (%s,%s,%d)\n",
chan->context,chan->exten, chan->priority+1);
LOCAL_USER_REMOVE(u);
}
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app_random);
}
int load_module(void)
{
srandom((unsigned int)getpid() + (unsigned int)time(NULL));
return ast_register_application(app_random, random_exec, random_synopsis, random_descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,104 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Trivial application to read a variable
*
* Copyright (C) 2003, Digium
*
* 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/app.h>
#include <asterisk/module.h>
#include <asterisk/translate.h>
#include <asterisk/options.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Read Variable Application";
static char *app = "Read";
static char *synopsis = "Read a variable";
static char *descrip =
" 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;
LOCAL_USER_DECL;
static int read_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct localuser *u;
char tmp[256];
char tmp2[128]="";
char *filename;
char *stringp;
if (!data || !strlen((char *)data)) {
ast_log(LOG_WARNING, "Read requires an argument (variable)\n");
return -1;
}
strncpy(tmp, (char *)data, sizeof(tmp)-1);
stringp=tmp;
strsep(&stringp, "|");
filename = strsep(&stringp, "|");
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) {
/* Answer if the line isn't up. */
res = ast_answer(chan);
}
if (!res) {
ast_stopstream(chan);
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;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, read_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -11,14 +11,12 @@
* 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/dsp.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
@@ -30,10 +28,9 @@ static char *app = "Record";
static char *synopsis = "Record to a file";
static char *descrip =
" Record(filename:extension|silence): Records from the channel into a given\n"
" Record(filename:extension): 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;
@@ -51,21 +48,13 @@ static int record_exec(struct ast_channel *chan, void *data)
char * vdata; /* Used so I don't have to typecast every use of *data */
int i = 0;
int j = 0;
struct ast_filestream *s = '\0';
struct localuser *u;
struct ast_frame *f = NULL;
struct ast_frame *f;
struct ast_dsp *sildet = NULL; /* silence detector dsp */
int totalsilence = 0;
int dspsilence = 0;
int silence = 0; /* amount of silence to allow */
int gotsilence = 0; /* did we timeout for silence? */
char silencestr[5];
int k = 0;
int rfmt = 0;
vdata = data; /* explained above */
/* The next few lines of code parse out the filename and header from the input string */
if (!vdata) { /* no data implies no filename or anything is present */
@@ -73,7 +62,7 @@ static int record_exec(struct ast_channel *chan, void *data)
return -1;
}
for (; vdata[i] && (vdata[i] != ':') && (vdata[i] != '|'); i++ ) {
for (; vdata[i] && (vdata[i] != ':') ; i++ ) {
if ((vdata[i] == '%') && (vdata[i+1] == 'd')) {
percentflag = 1; /* the wildcard is used */
}
@@ -86,21 +75,9 @@ static int record_exec(struct ast_channel *chan, void *data)
}
fil[i++] = '\0';
for (; j < 10 && i < strlen(data) && (vdata[i] != '|'); i++, j++)
for (; j < 10 && i < strlen(data); i++, j++)
ext[j] = vdata[i];
ext[j] = '\0';
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';
if (silencestr) {
silence = atoi(silencestr);
if (silence > 0)
silence *= 1000;
}
/* done parsing */
@@ -112,12 +89,12 @@ static int record_exec(struct ast_channel *chan, void *data)
count++;
} while ( ast_fileexists(tmp, ext, chan->language) != -1 );
} else
strncpy(tmp, fil, 256-1);
strncpy(tmp, fil, 256);
/* end of routine mentioned */
LOCAL_USER_ADD(u);
if (chan->_state != AST_STATE_UP) {
if (chan->state != AST_STATE_UP) {
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 */
}
@@ -126,39 +103,19 @@ static int record_exec(struct ast_channel *chan, void *data)
/* Some code to play a nice little beep to signify the start of the record operation */
res = ast_streamfile(chan, "beep", chan->language);
if (!res) {
printf("Waiting on stream\n");
res = ast_waitstream(chan, "");
} else {
printf("streamfile failed\n");
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", chan->name);
}
ast_stopstream(chan);
/* The end of beep code. Now the recording starts */
if (silence > 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;
}
sildet = ast_dsp_new();
if (!sildet) {
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
return -1;
}
ast_dsp_set_threshold(sildet, 256);
}
s = ast_writefile( tmp, ext, NULL, O_CREAT|O_TRUNC|O_WRONLY , 0, 0644);
if (s) {
while (ast_waitfor(chan, -1) > -1) {
f = ast_read(chan);
if (!f) {
res = -1;
break;
}
while ((f = ast_read(chan))) {
if (f->frametype == AST_FRAME_VOICE) {
res = ast_writestream(s, f);
@@ -166,30 +123,6 @@ static int record_exec(struct ast_channel *chan, void *data)
ast_log(LOG_WARNING, "Problem writing frame\n");
break;
}
if (silence > 0) {
dspsilence = 0;
ast_dsp_silence(sildet, f, &dspsilence);
if (dspsilence) {
totalsilence = dspsilence;
} else {
totalsilence = 0;
}
if (totalsilence > silence) {
/* Ended happily with silence */
ast_frfree(f);
gotsilence = 1;
break;
}
}
}
if (f->frametype == AST_FRAME_VIDEO) {
res = ast_writestream(s, f);
if (res) {
ast_log(LOG_WARNING, "Problem writing frame\n");
break;
}
}
if ((f->frametype == AST_FRAME_DTMF) &&
(f->subclass == '#')) {
@@ -202,15 +135,6 @@ static int record_exec(struct ast_channel *chan, void *data)
ast_log(LOG_DEBUG, "Got hangup\n");
res = -1;
}
if (gotsilence) {
ast_stream_rewind(s, silence-1000);
ast_truncstream(s);
} else {
/* Strip off the last 1/4 second of it */
ast_stream_rewind(s, 250);
ast_truncstream(s);
}
ast_closestream(s);
} else
ast_log(LOG_WARNING, "Could not create file %s\n", fil);
@@ -218,13 +142,6 @@ 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) {
res = ast_set_read_format(chan, rfmt);
if (res)
ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
if (sildet)
ast_dsp_free(sildet);
}
return res;
}

View File

@@ -1,742 +0,0 @@
/** @file app_rpt.c
*
* Asterisk -- A telephony toolkit for Linux.
*
* Radio Repeater program
*
* Copyright (C) 2002, Jim Dixon
*
* Jim Dixon <jim@lambdatel.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/options.h>
#include <asterisk/config.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <dirent.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <math.h>
#include <tonezone.h>
#include <linux/zaptel.h>
static char *tdesc = "Radio Repeater";
static int debug = 0;
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
#define MSWAIT 200
#define HANGTIME 5000
#define TOTIME 180000
#define IDTIME 300000
#define MAXRPTS 20
static pthread_t rpt_master_thread;
static struct rpt
{
char *name;
char *rxchanname;
char *txchanname;
char *ourcontext;
char *ourcallerid;
char *acctcode;
char *idrecording;
int hangtime;
int totime;
int idtime;
struct ast_channel *rxchannel,*txchannel,*pchannel;
int tailtimer,totimer,idtimer,txconf,pconf,callmode,cidx;
pthread_t rpt_id_thread,rpt_term_thread,rpt_proc_thread,rpt_call_thread;
char mydtmf,iding,terming;
char exten[AST_MAX_EXTENSION];
} rpt_vars[MAXRPTS];
static void *rpt_id(void *this)
{
ZT_CONFINFO ci; /* conference info */
int res;
struct rpt *myrpt = (struct rpt *)this;
struct ast_channel *mychannel;
/* allocate a pseudo-channel thru asterisk */
mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo");
if (!mychannel)
{
fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
pthread_exit(NULL);
}
/* make a conference for the tx */
ci.chan = 0;
ci.confno = myrpt->txconf; /* use the tx conference */
ci.confmode = ZT_CONF_CONFANN;
/* first put the channel on the conference in announce mode */
if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
pthread_exit(NULL);
}
myrpt->iding = 1;
ast_stopstream(mychannel);
res = ast_streamfile(mychannel, myrpt->idrecording, mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else {
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
res = 0;
}
myrpt->iding = 0;
ast_stopstream(mychannel);
ast_hangup(mychannel);
pthread_exit(NULL);
}
static void *rpt_proc(void *this)
{
ZT_CONFINFO ci; /* conference info */
int res;
struct rpt *myrpt = (struct rpt *)this;
struct ast_channel *mychannel;
/* wait a little bit */
usleep(1500000);
/* allocate a pseudo-channel thru asterisk */
mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo");
if (!mychannel)
{
fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
pthread_exit(NULL);
}
/* make a conference for the tx */
ci.chan = 0;
ci.confno = myrpt->pconf; /* use the tx conference */
ci.confmode = ZT_CONF_CONFANN;
/* first put the channel on the conference in announce mode */
if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
pthread_exit(NULL);
}
myrpt->terming = 1;
ast_stopstream(mychannel);
res = ast_streamfile(mychannel, "callproceeding", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else {
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
res = 0;
}
myrpt->terming = 0;
ast_stopstream(mychannel);
ast_hangup(mychannel);
pthread_exit(NULL);
}
static void *rpt_term(void *this)
{
ZT_CONFINFO ci; /* conference info */
int res;
struct rpt *myrpt = (struct rpt *)this;
struct ast_channel *mychannel;
/* wait a little bit */
usleep(1500000);
/* allocate a pseudo-channel thru asterisk */
mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo");
if (!mychannel)
{
fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
pthread_exit(NULL);
}
/* make a conference for the tx */
ci.chan = 0;
ci.confno = myrpt->pconf; /* use the tx conference */
ci.confmode = ZT_CONF_CONFANN;
/* first put the channel on the conference in announce mode */
if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
pthread_exit(NULL);
}
myrpt->terming = 1;
ast_stopstream(mychannel);
res = ast_streamfile(mychannel, "callterminated", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else {
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
res = 0;
}
myrpt->terming = 0;
ast_stopstream(mychannel);
ast_hangup(mychannel);
pthread_exit(NULL);
}
static void *rpt_call(void *this)
{
ZT_CONFINFO ci; /* conference info */
struct rpt *myrpt = (struct rpt *)this;
int res;
struct ast_frame *f,wf;
int stopped,congstarted;
struct ast_channel *mychannel,*genchannel;
myrpt->mydtmf = 0;
/* allocate a pseudo-channel thru asterisk */
mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo");
if (!mychannel)
{
fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
pthread_exit(NULL);
}
ci.chan = 0;
ci.confno = myrpt->pconf; /* use the pseudo conference */
ci.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER
| ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER;
/* first put the channel on the conference */
if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
ast_hangup(mychannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
/* allocate a pseudo-channel thru asterisk */
genchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo");
if (!genchannel)
{
fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
ast_hangup(mychannel);
pthread_exit(NULL);
}
ci.chan = 0;
ci.confno = myrpt->pconf;
ci.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER
| ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER;
/* first put the channel on the conference */
if (ioctl(genchannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
/* start dialtone */
if (tone_zone_play_tone(mychannel->fds[0],ZT_TONE_DIALTONE) < 0)
{
ast_log(LOG_WARNING, "Cannot start dialtone\n");
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
stopped = 0;
congstarted = 0;
while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
{
if ((myrpt->callmode == 1) && (myrpt->cidx > 0) && (!stopped))
{
stopped = 1;
/* stop dial tone */
tone_zone_play_tone(mychannel->fds[0],-1);
}
if ((myrpt->callmode == 4) && (!congstarted))
{
congstarted = 1;
/* start congestion tone */
tone_zone_play_tone(mychannel->fds[0],ZT_TONE_CONGESTION);
}
res = ast_waitfor(mychannel, MSWAIT);
if (res < 0)
{
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
if (res == 0) continue;
f = ast_read(mychannel);
if (f == NULL)
{
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
if ((f->frametype == AST_FRAME_CONTROL) &&
(f->subclass == AST_CONTROL_HANGUP))
{
ast_frfree(f);
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
ast_frfree(f);
}
/* stop any tone generation */
tone_zone_play_tone(mychannel->fds[0],-1);
/* end if done */
if (!myrpt->callmode)
{
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
if (myrpt->ourcallerid && *myrpt->ourcallerid)
{
if (mychannel->callerid) free(mychannel->callerid);
mychannel->callerid = strdup(myrpt->ourcallerid);
}
strcpy(mychannel->exten,myrpt->exten);
strcpy(mychannel->context,myrpt->ourcontext);
if (myrpt->acctcode)
strcpy(mychannel->accountcode,myrpt->acctcode);
mychannel->priority = 1;
ast_channel_undefer_dtmf(mychannel);
if (ast_pbx_start(mychannel) < 0)
{
ast_log(LOG_WARNING, "Unable to start PBX!!\n");
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
myrpt->callmode = 3;
while(myrpt->callmode)
{
if ((!mychannel->pvt) && (myrpt->callmode != 4))
{
myrpt->callmode = 4;
/* start congestion tone */
tone_zone_play_tone(genchannel->fds[0],ZT_TONE_CONGESTION);
}
if (myrpt->mydtmf)
{
wf.frametype = AST_FRAME_DTMF;
wf.subclass = myrpt->mydtmf;
wf.offset = 0;
wf.mallocd = 0;
wf.data = NULL;
wf.datalen = 0;
wf.samples = 0;
ast_write(genchannel,&wf);
myrpt->mydtmf = 0;
}
usleep(25000);
}
tone_zone_play_tone(genchannel->fds[0],-1);
if (mychannel->pvt) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
/* single thread with one file (request) to dial */
static void *rpt(void *this)
{
struct rpt *myrpt = (struct rpt *)this;
char *tele;
int ms = MSWAIT,lasttx,keyed,val;
struct ast_channel *who;
ZT_CONFINFO ci; /* conference info */
pthread_attr_t attr;
tele = strchr(myrpt->rxchanname,'/');
if (!tele)
{
fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
pthread_exit(NULL);
}
*tele++ = 0;
myrpt->rxchannel = ast_request(myrpt->rxchanname,AST_FORMAT_SLINEAR,tele);
if (myrpt->rxchannel)
{
ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
myrpt->rxchannel->whentohangup = 0;
myrpt->rxchannel->appl = "Apprpt";
myrpt->rxchannel->data = "(Repeater Rx)";
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
myrpt->rxchanname,tele,myrpt->rxchannel->name);
ast_call(myrpt->rxchannel,tele,999);
}
else
{
fprintf(stderr,"rpt:Sorry unable to obtain channel\n");
pthread_exit(NULL);
}
if (myrpt->txchanname)
{
tele = strchr(myrpt->txchanname,'/');
if (!tele)
{
fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
pthread_exit(NULL);
}
*tele++ = 0;
myrpt->txchannel = ast_request(myrpt->txchanname,AST_FORMAT_SLINEAR,tele);
if (myrpt->txchannel)
{
ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
myrpt->txchannel->whentohangup = 0;
myrpt->txchannel->appl = "Apprpt";
myrpt->txchannel->data = "(Repeater Rx)";
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
myrpt->txchanname,tele,myrpt->txchannel->name);
ast_call(myrpt->txchannel,tele,999);
}
else
{
fprintf(stderr,"rpt:Sorry unable to obtain channel\n");
pthread_exit(NULL);
}
}
else
{
myrpt->txchannel = myrpt->rxchannel;
}
/* allocate a pseudo-channel thru asterisk */
myrpt->pchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo");
if (!myrpt->pchannel)
{
fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
pthread_exit(NULL);
}
/* make a conference for the tx */
ci.chan = 0;
ci.confno = -1; /* make a new conf */
ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER;
/* first put the channel on the conference in announce mode */
if (ioctl(myrpt->txchannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
pthread_exit(NULL);
}
/* save tx conference number */
myrpt->txconf = ci.confno;
/* make a conference for the pseudo */
ci.chan = 0;
ci.confno = -1; /* make a new conf */
ci.confmode = ZT_CONF_CONFANNMON;
/* first put the channel on the conference in announce mode */
if (ioctl(myrpt->pchannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
pthread_exit(NULL);
}
/* save pseudo channel conference number */
myrpt->pconf = ci.confno;
/* Now, the idea here is to copy from the physical rx channel buffer
into the pseudo tx buffer, and from the pseudo rx buffer into the
tx channel buffer */
myrpt->tailtimer = 0;
myrpt->totimer = 0;
myrpt->idtimer = 0;
lasttx = 0;
keyed = 0;
myrpt->callmode = 0;
val = 0;
ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
val = 1;
ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
while (ms >= 0)
{
struct ast_frame *f;
struct ast_channel *cs[3];
int totx,elap;
totx = (keyed || myrpt->callmode || myrpt->iding || myrpt->terming);
if (!totx) myrpt->totimer = myrpt->totime;
else myrpt->tailtimer = myrpt->hangtime;
totx = (totx || myrpt->tailtimer) && myrpt->totimer;
/* if wants to transmit and in phone call, but timed out,
reset time-out timer if keyed */
if ((!totx) && (!myrpt->totimer) && myrpt->callmode && keyed)
{
myrpt->totimer = myrpt->totime;
continue;
}
if (totx && (!myrpt->idtimer))
{
myrpt->idtimer = myrpt->idtime;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&myrpt->rpt_id_thread,&attr,rpt_id,(void *) myrpt);
}
if (totx && (!lasttx))
{
lasttx = 1;
ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
}
if ((!totx) && lasttx)
{
lasttx = 0;
ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
}
cs[0] = myrpt->rxchannel;
cs[1] = myrpt->pchannel;
cs[2] = myrpt->txchannel;
ms = MSWAIT;
who = ast_waitfor_n(cs,3,&ms);
if (who == NULL) ms = 0;
elap = MSWAIT - ms;
if (myrpt->tailtimer) myrpt->tailtimer -= elap;
if (myrpt->tailtimer < 0) myrpt->tailtimer = 0;
if (myrpt->totimer) myrpt->totimer -= elap;
if (myrpt->totimer < 0) myrpt->totimer = 0;
if (myrpt->idtimer) myrpt->idtimer -= elap;
if (myrpt->idtimer < 0) myrpt->idtimer = 0;
if (!ms) continue;
if (who == myrpt->rxchannel) /* if it was a read from rx */
{
f = ast_read(myrpt->rxchannel);
if (!f)
{
if (debug) printf("@@@@ rpt:Hung Up\n");
break;
}
if (f->frametype == AST_FRAME_VOICE)
{
ast_write(myrpt->pchannel,f);
}
else if (f->frametype == AST_FRAME_DTMF)
{
char c;
c = (char) f->subclass; /* get DTMF char */
if ((!myrpt->callmode) && (c == '*'))
{
myrpt->callmode = 1;
myrpt->cidx = 0;
myrpt->exten[myrpt->cidx] = 0;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
continue;
}
if (myrpt->callmode && (c == '#'))
{
myrpt->callmode = 0;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&myrpt->rpt_term_thread,&attr,rpt_term,(void *) myrpt);
continue;
}
if (myrpt->callmode == 1)
{
myrpt->exten[myrpt->cidx++] = c;
myrpt->exten[myrpt->cidx] = 0;
/* if this exists */
if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
{
myrpt->callmode = 2;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&myrpt->rpt_proc_thread,&attr,rpt_proc,(void *) myrpt);
}
/* if can continue, do so */
if (ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL)) continue;
/* call has failed, inform user */
myrpt->callmode = 4;
continue;
}
if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
{
myrpt->mydtmf = f->subclass;
}
}
else if (f->frametype == AST_FRAME_CONTROL)
{
if (f->subclass == AST_CONTROL_HANGUP)
{
if (debug) printf("@@@@ rpt:Hung Up\n");
ast_frfree(f);
break;
}
/* if RX key */
if (f->subclass == AST_CONTROL_RADIO_KEY)
{
if (debug) printf("@@@@ rx key\n");
keyed = 1;
}
/* if RX un-key */
if (f->subclass == AST_CONTROL_RADIO_UNKEY)
{
if (debug) printf("@@@@ rx un-key\n");
keyed = 0;
}
}
ast_frfree(f);
}
if (who == myrpt->pchannel) /* if it was a read from pseudo */
{
f = ast_read(myrpt->pchannel);
if (!f)
{
if (debug) printf("@@@@ rpt:Hung Up\n");
break;
}
if (f->frametype == AST_FRAME_VOICE)
{
ast_write(myrpt->txchannel,f);
}
if (f->frametype == AST_FRAME_CONTROL)
{
if (f->subclass == AST_CONTROL_HANGUP)
{
if (debug) printf("@@@@ rpt:Hung Up\n");
ast_frfree(f);
break;
}
}
ast_frfree(f);
}
if (who == myrpt->txchannel) /* if it was a read from tx */
{
f = ast_read(myrpt->txchannel);
if (!f)
{
if (debug) printf("@@@@ rpt:Hung Up\n");
break;
}
if (f->frametype == AST_FRAME_CONTROL)
{
if (f->subclass == AST_CONTROL_HANGUP)
{
if (debug) printf("@@@@ rpt:Hung Up\n");
ast_frfree(f);
break;
}
}
ast_frfree(f);
}
}
ast_hangup(myrpt->pchannel);
ast_hangup(myrpt->rxchannel);
ast_hangup(myrpt->txchannel);
if (debug) printf("@@@@ rpt:Hung up channel\n");
pthread_exit(NULL);
return NULL;
}
static void *rpt_master(void *ignore)
{
struct ast_config *cfg;
char *this,*val;
int i,n;
/* start with blank config */
memset(&rpt_vars,0,sizeof(rpt_vars));
cfg = ast_load("rpt.conf");
if (!cfg) {
ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
pthread_exit(NULL);
}
/* go thru all the specified repeaters */
this = NULL;
n = 0;
while((this = ast_category_browse(cfg,this)) != NULL)
{
ast_log(LOG_DEBUG,"Loading config for repeater %s\n",this);
rpt_vars[n].name = this;
rpt_vars[n].rxchanname = ast_variable_retrieve(cfg,this,"rxchannel");
rpt_vars[n].txchanname = ast_variable_retrieve(cfg,this,"txchannel");
rpt_vars[n].ourcontext = ast_variable_retrieve(cfg,this,"context");
if (!rpt_vars[n].ourcontext) rpt_vars[n].ourcontext = this;
rpt_vars[n].ourcallerid = ast_variable_retrieve(cfg,this,"callerid");
rpt_vars[n].acctcode = ast_variable_retrieve(cfg,this,"accountcode");
rpt_vars[n].idrecording = ast_variable_retrieve(cfg,this,"idrecording");
val = ast_variable_retrieve(cfg,this,"hangtime");
if (val) rpt_vars[n].hangtime = atoi(val);
else rpt_vars[n].hangtime = HANGTIME;
val = ast_variable_retrieve(cfg,this,"totime");
if (val) rpt_vars[n].totime = atoi(val);
else rpt_vars[n].totime = TOTIME;
val = ast_variable_retrieve(cfg,this,"idtime");
if (val) rpt_vars[n].idtime = atoi(val);
else rpt_vars[n].idtime = IDTIME;
n++;
}
ast_log(LOG_DEBUG, "Total of %d repeaters configured.\n",n);
/* start em all */
for(i = 0; i < n; i++)
{
if (!rpt_vars[i].rxchanname)
{
ast_log(LOG_WARNING,"Did not specify rxchanname for repeater %s\n",rpt_vars[i].name);
pthread_exit(NULL);
}
if (!rpt_vars[i].idrecording)
{
ast_log(LOG_WARNING,"Did not specify idrecording for repeater %s\n",rpt_vars[i].name);
pthread_exit(NULL);
}
pthread_create(&rpt_vars[i].rpt_id_thread,NULL,rpt,(void *) &rpt_vars[i]);
}
/* wait for first one to die (should be never) */
pthread_join(rpt_vars[0].rpt_id_thread,NULL);
pthread_exit(NULL);
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return 0;
}
int load_module(void)
{
pthread_create(&rpt_master_thread,NULL,rpt_master,NULL);
return 0;
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,121 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* SayUnixTime application
*
* Copyright (c) 2003 Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <app_sayunixtime__200309@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/file.h>
#include <asterisk/logger.h>
#include <asterisk/options.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/say.h>
static char *tdesc = "Say time";
static char *app_sayunixtime = "SayUnixTime";
static char *sayunixtime_synopsis = "Says a specified time in a custom format";
static char *sayunixtime_descrip =
"SayUnixTime([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;
LOCAL_USER_DECL;
static int sayunixtime_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char *s,*zone=NULL,*timec;
time_t unixtime;
char *format = "ABdY 'digits/at' IMp";
struct timeval tv;
LOCAL_USER_ADD(u);
gettimeofday(&tv,NULL);
unixtime = (time_t)tv.tv_sec;
if (data) {
s = data;
s = ast_strdupa(s);
if (s) {
timec = strsep(&s,"|");
if ((timec) && (*timec != '\0')) {
long timein;
if (sscanf(timec,"%ld",&timein) == 1) {
unixtime = (time_t)timein;
}
}
if (s) {
zone = strsep(&s,"|");
if (zone && (*zone == '\0'))
zone = NULL;
if (s) {
format = s;
}
}
} else {
ast_log(LOG_ERROR, "Out of memory error\n");
}
}
if (chan->_state != AST_STATE_UP) {
res = ast_answer(chan);
}
if (!res)
res = ast_say_date_with_format(chan, unixtime, AST_DIGIT_ANY, chan->language, format, zone);
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app_sayunixtime);
}
int load_module(void)
{
return ast_register_application(app_sayunixtime, sayunixtime_exec, sayunixtime_synopsis, sayunixtime_descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,99 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* App to send DTMF digits
*
* 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/module.h>
#include <asterisk/translate.h>
#include <asterisk/options.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Send DTMF digits Application";
static char *app = "SendDTMF";
static char *synopsis = "Sends arbitrary DTMF digits";
static char *descrip =
" SendDTMF(digits): Sends DTMF digits on a channel. Returns 0 on success"
"or -1 on a hangup.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int senddtmf_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct localuser *u;
char *digits = data;
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);
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;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, senddtmf_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,88 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* App to set callerid
*
* 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/module.h>
#include <asterisk/translate.h>
#include <asterisk/image.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Set CallerID Application";
static char *app = "SetCallerID";
static char *synopsis = "Set CallerID";
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;
char tmp[256] = "";
struct localuser *u;
char *opt;
int anitoo = 0;
if (data)
strncpy(tmp, (char *)data, sizeof(tmp) - 1);
opt = strchr(tmp, '|');
if (opt) {
*opt = '\0';
opt++;
if (*opt == 'a')
anitoo = 1;
}
LOCAL_USER_ADD(u);
ast_set_callerid(chan, strlen(tmp) ? tmp : NULL, anitoo);
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, setcallerid_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,127 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Applictions connected with CDR engine
*
* Copyright (C) 2003, Digium
*
* Justin Huff <jjhuff@mspin.net>
*
* 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/pbx.h>
#include <asterisk/logger.h>
#include <stdlib.h>
#include <string.h>
static char *tdesc = "CDR user field apps";
static char *setcdruserfield_descrip =
"[Synopsis]\n"
"SetCDRUserField(value)\n\n"
"[Description]\n"
"SetCDRUserField(value): Set the CDR 'user field' to value\n"
" The Call Data Record (CDR) user field is an extra field you\n"
" can use for data not stored anywhere else in the record.\n"
" CDR records can be used for billing or storing other arbitrary data\n"
" (I.E. telephone survey responses)\n"
" Also see AppendCDRUserField().\n"
" Always returns 0\n";
static char *setcdruserfield_app = "SetCDRUserField";
static char *setcdruserfield_synopsis = "Set the CDR user field";
static char *appendcdruserfield_descrip =
"[Synopsis]\n"
"AppendCDRUserField(value)\n\n"
"[Description]\n"
"AppendCDRUserField(value): Append value to the CDR user field\n"
" The Call Data Record (CDR) user field is an extra field you\n"
" can use for data not stored anywhere else in the record.\n"
" CDR records can be used for billing or storing other arbitrary data\n"
" (I.E. telephone survey responses)\n"
" Also see SetCDRUserField().\n"
" Always returns 0\n";
static char *appendcdruserfield_app = "AppendCDRUserField";
static char *appendcdruserfield_synopsis = "Append to the CDR user field";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int setcdruserfield_exec(struct ast_channel *chan, void *data)
{
struct localuser *u;
int res = 0;
LOCAL_USER_ADD(u)
if (chan->cdr && data)
{
ast_cdr_setuserfield(chan, (char*)data);
}
LOCAL_USER_REMOVE(u);
return res;
}
static int appendcdruserfield_exec(struct ast_channel *chan, void *data)
{
struct localuser *u;
int res = 0;
LOCAL_USER_ADD(u)
if (chan->cdr && data)
{
ast_cdr_appenduserfield(chan, (char*)data);
}
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
int res;
STANDARD_HANGUP_LOCALUSERS;
res = ast_unregister_application(setcdruserfield_app);
res |= ast_unregister_application(appendcdruserfield_app);
return res;
}
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);
return res;
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,107 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* App to set callerid
*
* 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/module.h>
#include <asterisk/translate.h>
#include <asterisk/image.h>
#include <asterisk/callerid.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Set CallerID Name";
static char *app = "SetCIDName";
static char *synopsis = "Set CallerID Name";
static char *descrip =
" SetCIDName(cname[|a]): Set Caller*ID Name on a call to a new\n"
"value, while preserving the original Caller*ID number. This is\n"
"useful for providing additional information to the called\n"
"party. 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;
char tmp[256] = "";
char oldcid[256] = "", *l, *n;
char newcid[256] = "";
struct localuser *u;
char *opt;
int anitoo = 0;
if (data)
strncpy(tmp, (char *)data, sizeof(tmp) - 1);
opt = strchr(tmp, '|');
if (opt) {
*opt = '\0';
opt++;
if (*opt == 'a')
anitoo = 1;
}
LOCAL_USER_ADD(u);
if (chan->callerid) {
strncpy(oldcid, chan->callerid, sizeof(oldcid) - 1);
ast_callerid_parse(oldcid, &n, &l);
n = tmp;
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 && strlen(l)) {
strncpy(newcid, l, sizeof(newcid) - 1);
}
} else
strncpy(newcid, tmp, sizeof(newcid));
ast_set_callerid(chan, strlen(newcid) ? newcid : NULL, anitoo);
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, setcallerid_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,108 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* App to set callerid
*
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
* Oliver Daudey <traveler@xs4all.nl>
*
* 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/image.h>
#include <asterisk/callerid.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Set CallerID Number";
static char *app = "SetCIDNum";
static char *synopsis = "Set CallerID Number";
static char *descrip =
" SetCIDNum(cnum[|a]): Set Caller*ID Number on a call to a new\n"
"value, while preserving the original Caller*ID name. This is\n"
"useful for providing additional information to the called\n"
"party. 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;
char tmp[256] = "";
char oldcid[256] = "", *l, *n;
char newcid[256] = "";
struct localuser *u;
char *opt;
int anitoo = 0;
if (data)
strncpy(tmp, (char *)data, sizeof(tmp) - 1);
opt = strchr(tmp, '|');
if (opt) {
*opt = '\0';
opt++;
if (*opt == 'a')
anitoo = 1;
}
LOCAL_USER_ADD(u);
if (chan->callerid) {
strncpy(oldcid, chan->callerid, sizeof(oldcid) - 1);
ast_callerid_parse(oldcid, &n, &l);
l = tmp;
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 && strlen(n)) {
strncpy(newcid, n, sizeof(newcid) - 1);
}
} else
strncpy(newcid, tmp, sizeof(newcid));
ast_set_callerid(chan, strlen(newcid) ? newcid : NULL, anitoo);
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, setcallerid_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,13 +19,14 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Trivial skeleton Application";
static char *app = "skel";
static char *synopsis =
" This is a skeleton application that shows you the basic structure to create your\n"
"own asterisk applications.\n";
STANDARD_LOCAL_USER;
@@ -53,7 +54,7 @@ int unload_module(void)
int load_module(void)
{
return ast_register_application(app, skel_exec, synopsis, tdesc);
return ast_register_application(app, skel_exec);
}
char *description(void)

View File

@@ -1,89 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* SoftHangup application
*
* 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 <sys/types.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.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";
static char *desc = " SoftHangup(Technology/resource)\n"
"Hangs up the requested channel. Always returns 0\n";
static char *app = "SoftHangup";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int softhangup_exec(struct ast_channel *chan, void *data)
{
struct localuser *u;
struct ast_channel *c=NULL;
if (!data) {
ast_log(LOG_WARNING, "SoftHangup requires an argument (Technology/resource)\n");
return 0;
}
LOCAL_USER_ADD(u);
c = ast_channel_walk(NULL);
while (c) {
if (!strcasecmp(c->name, data)) {
ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
break;
}
c = ast_channel_walk(c);
}
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, softhangup_exec, synopsis, desc);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,552 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Connect to PostgreSQL
*
* Copyright (C) 2002, Christos Ricudis
*
* Christos Ricudis <ricudis@paiko.gr>
*
* 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/module.h>
#include <asterisk/linkedlists.h>
#include <asterisk/chanvars.h>
#include <asterisk/lock.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include "libpq-fe.h"
static char *tdesc = "Simple PostgreSQL Interface";
static char *app = "PGSQL";
static char *synopsis = "Do several SQLy things";
static char *descrip =
" PGSQL(): Do several SQLy things\n";
/*
Syntax of SQL commands :
Connect #var option-string
Connects to a database using the option-string and stores the
connection identifier in $var
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
Fetches a row from the query and stores end-of-table status in
${statusvar} and columns in ${var1}..${varn}
Clear result-identifier
Clears data structures associated with result-identifier
Disconnect connection-identifier
Disconnects from named connection
EXAMPLES OF USE :
(
$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}";
*/
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
extern void pbx_builtin_setvar_helper(struct ast_channel *chan, char *name, char *value);
#define AST_PGSQL_ID_DUMMY 0
#define AST_PGSQL_ID_CONNID 1
#define AST_PGSQL_ID_RESID 2
#define AST_PGSQL_ID_FETCHID 3
struct ast_PGSQL_id {
int identifier_type; /* 0=dummy, 1=connid, 2=resultid */
int identifier;
void *data;
AST_LIST_ENTRY(ast_PGSQL_id) entries;
} *ast_PGSQL_id;
AST_LIST_HEAD(PGSQLidshead,ast_PGSQL_id) PGSQLidshead;
static void *find_identifier(int identifier,int identifier_type) {
struct PGSQLidshead *headp;
struct ast_PGSQL_id *i;
void *res=NULL;
int found=0;
headp=&PGSQLidshead;
if (AST_LIST_LOCK(headp)) {
ast_log(LOG_WARNING,"Unable to lock identifiers list\n");
} else {
AST_LIST_TRAVERSE(headp,i,entries) {
if ((i->identifier==identifier) && (i->identifier_type==identifier_type)) {
found=1;
res=i->data;
break;
}
}
if (!found) {
ast_log(LOG_WARNING,"Identifier %d, identifier_type %d not found in identifier list\n",identifier,identifier_type);
}
AST_LIST_UNLOCK(headp);
}
return(res);
}
static int add_identifier(int identifier_type,void *data) {
struct ast_PGSQL_id *i,*j;
struct PGSQLidshead *headp;
int maxidentifier=0;
headp=&PGSQLidshead;
i=NULL;
j=NULL;
if (AST_LIST_LOCK(headp)) {
ast_log(LOG_WARNING,"Unable to lock identifiers list\n");
return(-1);
} else {
i=malloc(sizeof(struct ast_PGSQL_id));
AST_LIST_TRAVERSE(headp,j,entries) {
if (j->identifier>maxidentifier) {
maxidentifier=j->identifier;
}
}
i->identifier=maxidentifier+1;
i->identifier_type=identifier_type;
i->data=data;
AST_LIST_INSERT_HEAD(headp,i,entries);
AST_LIST_UNLOCK(headp);
}
return(i->identifier);
}
static int del_identifier(int identifier,int identifier_type) {
struct ast_PGSQL_id *i;
struct PGSQLidshead *headp;
int found=0;
headp=&PGSQLidshead;
if (AST_LIST_LOCK(headp)) {
ast_log(LOG_WARNING,"Unable to lock identifiers list\n");
} else {
AST_LIST_TRAVERSE(headp,i,entries) {
if ((i->identifier==identifier) &&
(i->identifier_type==identifier_type)) {
AST_LIST_REMOVE(headp,i,ast_PGSQL_id,entries);
free(i);
found=1;
break;
}
}
AST_LIST_UNLOCK(headp);
}
if (found==0) {
ast_log(LOG_WARNING,"Could not find identifier %d, identifier_type %d in list to delete\n",identifier,identifier_type);
return(-1);
} else {
return(0);
}
}
static int aPGSQL_connect(struct ast_channel *chan, void *data) {
char *s1,*s4;
char s[100];
char *optionstring;
char *var;
int l;
int res;
PGconn *karoto;
int id;
char *stringp=NULL;
res=0;
l=strlen(data)+2;
s1=malloc(l);
strncpy(s1,data,l);
stringp=s1;
strsep(&stringp," "); // eat the first token, we already know it :P
var=strsep(&stringp," ");
optionstring=strsep(&stringp,"\n");
karoto = PQconnectdb(optionstring);
if (PQstatus(karoto) == CONNECTION_BAD) {
ast_log(LOG_WARNING,"Connection to database using '%s' failed. postgress reports : %s\n", optionstring,
PQerrorMessage(karoto));
res=-1;
} else {
ast_log(LOG_WARNING,"adding identifier\n");
id=add_identifier(AST_PGSQL_ID_CONNID,karoto);
s4=&s[0];
sprintf(s4,"%d",id);
pbx_builtin_setvar_helper(chan,var,s);
}
free(s1);
return res;
}
static int aPGSQL_query(struct ast_channel *chan, void *data) {
char *s1,*s2,*s3,*s4,*s5;
char s[100];
char *querystring;
char *var;
int l;
int res,nres;
PGconn *karoto;
PGresult *PGSQLres;
int id,id1;
char *stringp=NULL;
res=0;
l=strlen(data)+2;
s1=malloc(l);
s2=malloc(l);
strcpy(s1,data);
stringp=s1;
strsep(&stringp," "); // eat the first token, we already know it :P
s3=strsep(&stringp," ");
while (1) { // ugly trick to make branches with break;
var=s3;
s4=strsep(&stringp," ");
id=atoi(s4);
querystring=strsep(&stringp,"\n");
if ((karoto=find_identifier(id,AST_PGSQL_ID_CONNID))==NULL) {
ast_log(LOG_WARNING,"Invalid connection identifier %d passed in aPGSQL_query\n",id);
res=-1;
break;
}
PGSQLres=PQexec(karoto,querystring);
if (PGSQLres==NULL) {
ast_log(LOG_WARNING,"aPGSQL_query: Connection Error (connection identifier = %d, error message : %s)\n",id,PQerrorMessage(karoto));
res=-1;
break;
}
if (PQresultStatus(PGSQLres) == PGRES_BAD_RESPONSE ||
PQresultStatus(PGSQLres) == PGRES_NONFATAL_ERROR ||
PQresultStatus(PGSQLres) == PGRES_FATAL_ERROR) {
ast_log(LOG_WARNING,"aPGSQL_query: Query Error (connection identifier : %d, error message : %s)\n",id,PQcmdStatus(PGSQLres));
res=-1;
break;
}
nres=PQnfields(PGSQLres);
id1=add_identifier(AST_PGSQL_ID_RESID,PGSQLres);
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,*s3,*s4,*s5,*s6,*s7;
char s[100];
char *var;
int l;
int res;
PGresult *PGSQLres;
int id,id1,i,j,fnd;
int *lalares=NULL;
int nres;
struct ast_var_t *variables;
struct varshead *headp;
char *stringp=NULL;
headp=&chan->varshead;
res=0;
l=strlen(data)+2;
s7=NULL;
s1=malloc(l);
s2=malloc(l);
strcpy(s1,data);
stringp=s1;
strsep(&stringp," "); // eat the first token, we already know it :P
s3=strsep(&stringp," ");
while (1) { // ugly trick to make branches with break;
var=s3; // fetchid
fnd=0;
AST_LIST_TRAVERSE(headp,variables,entries) {
if (strncasecmp(ast_var_name(variables),s3,strlen(s3))==0) {
s7=ast_var_value(variables);
fnd=1;
break;
}
}
if (fnd==0) {
s7="0";
pbx_builtin_setvar_helper(chan,s3,s7);
}
s4=strsep(&stringp," ");
id=atoi(s4); // resultid
if ((PGSQLres=find_identifier(id,AST_PGSQL_ID_RESID))==NULL) {
ast_log(LOG_WARNING,"Invalid result identifier %d passed in aPGSQL_fetch\n",id);
res=-1;
break;
}
id=atoi(s7); //fetchid
if ((lalares=find_identifier(id,AST_PGSQL_ID_FETCHID))==NULL) {
i=0;
} else {
i=*lalares;
free(lalares);
del_identifier(id,AST_PGSQL_ID_FETCHID);
}
nres=PQnfields(PGSQLres);
ast_log(LOG_WARNING,"ast_PGSQL_fetch : nres = %d i = %d ;\n",nres,i);
for (j=0;j<nres;j++) {
s5=strsep(&stringp," ");
if (s5==NULL) {
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);
break;
}
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;
id1=add_identifier(AST_PGSQL_ID_FETCHID,lalares);
} else {
id1=0;
}
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;
}
free(s1);
free(s2);
return(res);
}
static int aPGSQL_reset(struct ast_channel *chan, void *data) {
char *s1,*s3;
int l;
PGconn *karoto;
int id;
char *stringp=NULL;
l=strlen(data)+2;
s1=malloc(l);
strcpy(s1,data);
stringp=s1;
strsep(&stringp," "); // eat the first token, we already know it :P
s3=strsep(&stringp," ");
id=atoi(s3);
if ((karoto=find_identifier(id,AST_PGSQL_ID_CONNID))==NULL) {
ast_log(LOG_WARNING,"Invalid connection identifier %d passed in aPGSQL_reset\n",id);
} else {
PQreset(karoto);
}
free(s1);
return(0);
}
static int aPGSQL_clear(struct ast_channel *chan, void *data) {
char *s1,*s3;
int l;
PGresult *karoto;
int id;
char *stringp=NULL;
l=strlen(data)+2;
s1=malloc(l);
strcpy(s1,data);
stringp=s1;
strsep(&stringp," "); // eat the first token, we already know it :P
s3=strsep(&stringp," ");
id=atoi(s3);
if ((karoto=find_identifier(id,AST_PGSQL_ID_RESID))==NULL) {
ast_log(LOG_WARNING,"Invalid result identifier %d passed in aPGSQL_clear\n",id);
} else {
PQclear(karoto);
del_identifier(id,AST_PGSQL_ID_RESID);
}
free(s1);
return(0);
}
static int aPGSQL_disconnect(struct ast_channel *chan, void *data) {
char *s1,*s3;
int l;
PGconn *karoto;
int id;
char *stringp=NULL;
l=strlen(data)+2;
s1=malloc(l);
strcpy(s1,data);
stringp=s1;
strsep(&stringp," "); // eat the first token, we already know it :P
s3=strsep(&stringp," ");
id=atoi(s3);
if ((karoto=find_identifier(id,AST_PGSQL_ID_CONNID))==NULL) {
ast_log(LOG_WARNING,"Invalid connection identifier %d passed in aPGSQL_disconnect\n",id);
} else {
PQfinish(karoto);
del_identifier(id,AST_PGSQL_ID_CONNID);
}
free(s1);
return(0);
}
static int aPGSQL_debug(struct ast_channel *chan, void *data) {
ast_log(LOG_WARNING,"Debug : %s\n",(char *)data);
return(0);
}
static int PGSQL_exec(struct ast_channel *chan, void *data)
{
struct localuser *u;
int result;
if (!data) {
ast_log(LOG_WARNING, "APP_PGSQL requires an argument (see manual)\n");
return -1;
}
LOCAL_USER_ADD(u);
result=0;
if (strncasecmp("connect",data,strlen("connect"))==0) {
result=(aPGSQL_connect(chan,data));
} else if (strncasecmp("query",data,strlen("query"))==0) {
result=(aPGSQL_query(chan,data));
} else if (strncasecmp("fetch",data,strlen("fetch"))==0) {
result=(aPGSQL_fetch(chan,data));
} else if (strncasecmp("reset",data,strlen("reset"))==0) {
result=(aPGSQL_reset(chan,data));
} else if (strncasecmp("clear",data,strlen("clear"))==0) {
result=(aPGSQL_clear(chan,data));
} else if (strncasecmp("debug",data,strlen("debug"))==0) {
result=(aPGSQL_debug(chan,data));
} else if (strncasecmp("disconnect",data,strlen("disconnect"))==0) {
result=(aPGSQL_disconnect(chan,data));
} else {
ast_log(LOG_WARNING, "Unknown APP_PGSQL argument : %s\n",(char *)data);
result=-1;
}
LOCAL_USER_REMOVE(u);
return result;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
struct PGSQLidshead *headp;
headp=&PGSQLidshead;
AST_LIST_HEAD_INIT(headp);
return ast_register_application(app, PGSQL_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,88 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Skeleton application
*
* 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 <sys/types.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.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 =
" StripLSD(count): Strips the trailing 'count' digits from the channel's\n"
"associated extension. For example, the number 5551212 when stripped with a\n"
"count of 4 would be changed to 555. This app always returns 0, and the PBX\n"
"will continue processing at the next priority for the *new* extension.\n"
" So, for example, if priority 3 of 5551212 is StripLSD 4, the next step\n"
"executed will be priority 4 of 555. If you switch into an extension which\n"
"has no first step, the PBX will treat it as though the user dialed an\n"
"invalid extension.\n";
static char *app = "StripLSD";
static char *synopsis = "Strip Least Significant Digits";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int striplsd_exec(struct ast_channel *chan, void *data)
{
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)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, striplsd_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,133 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Skeleton application
*
* 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 <sys/types.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/pbx.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Save substring digits in a given variable";
static char *descrip =
" 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"
"left. If it's negative, we move count1 digits counting from the end of\n"
"the string to the left. Parameter count2 implies how many digits we are\n"
"taking from the point that count1 placed us. If count2 is negative, then\n"
"that many digits are omitted from the end.\n"
"For example:\n"
"exten => _NXXXXXX,1,SubString,test=2564286161|0|3\n"
"assigns the area code (3 first digits) to variable test.\n"
"exten => _NXXXXXX,1,SubString,test=2564286161|-7|7\n"
"assigns the last 7 digits to variable test.\n"
"exten => _NXXXXXX,1,SubString,test=2564286161|0|-4\n"
"assigns all but the last 4 digits to variable test.\n"
"If there are no parameters it'll return with -1.\n"
"If there wrong parameters it go on and return with 0\n";
static char *app = "SubString";
static char *synopsis = "Save substring digits in a given variable";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
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)+1);
if (strchr(stringp,'|')&&strchr(stringp,'=')) {
int icount1,icount2;
first=strsep(&stringp,"=");
second=strsep(&stringp,"|");
count1=strsep(&stringp,"|");
count2=strsep(&stringp,"\0");
if (!first || !second || !count1 || !count2) {
ast_log(LOG_DEBUG, "Ignoring, since there is no argument: variable or string or count1 or count2\n");
return 0;
}
icount1=atoi(count1);
icount2=atoi(count2);
if (icount2<0) {
icount2 = icount2 + strlen(second);
}
if (abs(icount1)>strlen(second)) {
ast_log(LOG_WARNING, "Limiting count1 parameter because it exceeds the length of the string\n");
if (icount1>=0)
icount1=strlen(second);
else
icount1=0;
}
if ((icount1<0 && icount2>-icount1) || (icount1>=0 && icount1+icount2>strlen(second))) {
ast_log(LOG_WARNING, "Limiting count2 parameter because it exceeds the length of the string\n");
if (icount1>=0)
icount2=strlen(second)-icount1;
else
icount2=strlen(second)+icount1;
}
if (first&&second) {
if (icount1>=0)
strncpy(newexten,second+icount1,icount2);
else
strncpy(newexten,second+strlen(second)+icount1,icount2);
pbx_builtin_setvar_helper(chan,first,newexten);
}
} else {
ast_log(LOG_DEBUG, "Ignoring, no parameters\n");
}
return 0;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, substring_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -11,7 +11,6 @@
* the GNU General Public License
*/
#include <asterisk/lock.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
@@ -42,7 +41,7 @@ STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int system_exec(struct ast_channel *chan, void *data)
static int skel_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
@@ -54,10 +53,10 @@ static int system_exec(struct ast_channel *chan, void *data)
/* Do our thing here */
res = system((char *)data);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data);
ast_log(LOG_WARNING, "Unable to execute '%s'\n", data);
res = -1;
} else if (res == 127) {
ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data);
ast_log(LOG_WARNING, "Unable to execute '%s'\n", data);
res = -1;
} else {
if (res && ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
@@ -76,7 +75,7 @@ int unload_module(void)
int load_module(void)
{
return ast_register_application(app, system_exec, synopsis, descrip);
return ast_register_application(app, skel_exec, synopsis, descrip);
}
char *description(void)

View File

@@ -1,94 +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/module.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Transfer";
static char *app = "Transfer";
static char *synopsis = "Transfer caller to remote extension";
static char *descrip =
" Transfer(exten): Requests the remote caller be transferred to\n"
"a given extension. Returns -1 on hangup, or 0 on completion\n"
"regardless of whether the transfer was successful. If the transfer\n"
"was *not* supported or 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 transfer_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
if (!data || !strlen(data)) {
ast_log(LOG_WARNING, "Transfer requires an argument (destination)\n");
res = 1;
}
LOCAL_USER_ADD(u);
if (!res) {
res = ast_transfer(chan, data);
}
if (!res) {
/* Look for a "busy" place */
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
chan->priority += 100;
}
if (res > 0)
res = 0;
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, transfer_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -11,7 +11,6 @@
* the GNU General Public License
*/
#include <asterisk/lock.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
@@ -52,15 +51,13 @@ static int sendurl_exec(struct ast_channel *chan, void *data)
char *options;
int option_wait=0;
struct ast_frame *f;
char *stringp=NULL;
if (!data || !strlen((char *)data)) {
ast_log(LOG_WARNING, "SendURL requires an argument (URL)\n");
return -1;
}
strncpy(tmp, (char *)data, sizeof(tmp)-1);
stringp=tmp;
strsep(&stringp, "|");
options = strsep(&stringp, "|");
strncpy(tmp, (char *)data, sizeof(tmp));
strtok(tmp, "|");
options = strtok(NULL, "|");
if (options && !strcasecmp(options, "wait"))
option_wait = 1;
LOCAL_USER_ADD(u);

File diff suppressed because it is too large Load Diff

View File

@@ -1,131 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Wait for Ring Application
*
* Copyright (C) 2003, Digium
*
* 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 <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/options.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";
static char *desc = " WaitForRing(timeout)\n"
"Returns 0 after waiting at least timeout seconds. and\n"
"only after the next ring has completed. Returns 0 on\n"
"success or -1 on hangup\n";
static char *app = "WaitForRing";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int waitforring_exec(struct ast_channel *chan, void *data)
{
struct localuser *u;
struct ast_frame *f;
int res = 0;
int ms;
if (!data || (sscanf(data, "%d", &ms) != 1)) {
ast_log(LOG_WARNING, "SoftHangup requires an argument (minimum seconds)\n");
return 0;
}
ms *= 1000;
LOCAL_USER_ADD(u);
while(ms > 0) {
ms = ast_waitfor(chan, ms);
if (ms < 0) {
res = ms;
break;
}
if (ms > 0) {
f = ast_read(chan);
if (!f) {
res = -1;
break;
}
if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Got a ring but still waiting for timeout\n");
}
ast_frfree(f);
}
}
/* Now we're really ready for the ring */
if (!res) {
ms = 99999999;
while(ms > 0) {
ms = ast_waitfor(chan, ms);
if (ms < 0) {
res = ms;
break;
}
if (ms > 0) {
f = ast_read(chan);
if (!f) {
res = -1;
break;
}
if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Got a ring after the timeout\n");
ast_frfree(f);
break;
}
ast_frfree(f);
}
}
}
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, waitforring_exec, synopsis, desc);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,116 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Playback the special information tone to get rid of telemarketers
*
* 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/module.h>
#include <asterisk/translate.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Block Telemarketers with Special Information Tone";
static char *app = "Zapateller";
static char *synopsis = "Block telemarketers with SIT";
static char *descrip =
" Zapateller(options): Generates special information tone to block\n"
"telemarketers from calling you. Returns 0 normally or -1 on hangup.\n"
"Options is a pipe-delimited list of options. The following options\n"
"are available: 'answer' causes the line to be answered before playing\n"
"the tone, 'nocallerid' causes Zapateller to only play the tone if there\n"
"is no callerid information available. Options should be separated by |\n"
"characters\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int zapateller_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct localuser *u;
int answer = 0, nocallerid = 0;
char *c;
char *stringp=NULL;
LOCAL_USER_ADD(u);
stringp=data;
c = strsep(&stringp, "|");
while(c && strlen(c)) {
if (!strcasecmp(c, "answer"))
answer = 1;
else if (!strcasecmp(c, "nocallerid"))
nocallerid = 1;
c = strsep(&stringp, "|");
}
ast_stopstream(chan);
if (chan->_state != AST_STATE_UP) {
if (answer)
res = ast_answer(chan);
if (!res) {
res = ast_safe_sleep(chan, 500);
}
}
if (chan->callerid && nocallerid) {
LOCAL_USER_REMOVE(u);
return res;
}
if (!res)
res = ast_tonepair(chan, 950, 0, 330, 0);
if (!res)
res = ast_tonepair(chan, 1400, 0, 330, 0);
if (!res)
res = ast_tonepair(chan, 1800, 0, 330, 0);
if (!res)
res = ast_tonepair(chan, 0, 0, 1000, 0);
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, zapateller_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,305 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Zap Barge support
*
* Copyright (C) 2003, Digium
*
* Mark Spencer <markster@digium.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*
* Special thanks to comphealth.com for sponsoring this
* GPL application.
*/
#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/config.h>
#include <asterisk/app.h>
#include <asterisk/options.h>
#include <asterisk/cli.h>
#include <asterisk/say.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <linux/zaptel.h>
static char *tdesc = "Barge in on Zap channel application";
static char *app = "ZapBarge";
static char *synopsis = "Barge in (monitor) Zap channel";
static char *descrip =
" ZapBarge([channel]): Barges in on a specified zap\n"
"channel or prompts if one is not specified. Returns\n"
"-1 when caller user hangs up and is independent of the\n"
"state of the channel being monitored.";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
#define CONF_SIZE 160
static int careful_write(int fd, unsigned char *data, int len)
{
int res;
while(len) {
res = write(fd, data, len);
if (res < 1) {
if (errno != EAGAIN) {
ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno));
return -1;
} else
return 0;
}
len -= res;
data += res;
}
return 0;
}
static int conf_run(struct ast_channel *chan, int confno, int confflags)
{
int fd;
struct zt_confinfo ztc;
struct ast_frame *f;
struct ast_channel *c;
struct ast_frame fr;
int outfd;
int ms;
int nfds;
int res;
int flags;
int retryzap;
int origfd;
int ret = -1;
ZT_BUFFERINFO bi;
char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
char *buf = __buf + AST_FRIENDLY_OFFSET;
/* Set it into U-law mode (write) */
if (ast_set_write_format(chan, AST_FORMAT_ULAW) < 0) {
ast_log(LOG_WARNING, "Unable to set '%s' to write ulaw mode\n", chan->name);
goto outrun;
}
/* Set it into U-law mode (read) */
if (ast_set_read_format(chan, AST_FORMAT_ULAW) < 0) {
ast_log(LOG_WARNING, "Unable to set '%s' to read ulaw mode\n", chan->name);
goto outrun;
}
ast_indicate(chan, -1);
retryzap = strcasecmp(chan->type, "Zap");
zapretry:
origfd = chan->fds[0];
if (retryzap) {
fd = open("/dev/zap/pseudo", O_RDWR);
if (fd < 0) {
ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
goto outrun;
}
/* Make non-blocking */
flags = fcntl(fd, F_GETFL);
if (flags < 0) {
ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno));
close(fd);
goto outrun;
}
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno));
close(fd);
goto outrun;
}
/* Setup buffering information */
memset(&bi, 0, sizeof(bi));
bi.bufsize = CONF_SIZE;
bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
bi.numbufs = 4;
if (ioctl(fd, ZT_SET_BUFINFO, &bi)) {
ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno));
close(fd);
goto outrun;
}
nfds = 1;
} else {
/* XXX Make sure we're not running on a pseudo channel XXX */
fd = chan->fds[0];
nfds = 0;
}
memset(&ztc, 0, sizeof(ztc));
/* Check to see if we're in a conference... */
ztc.chan = 0;
if (ioctl(fd, ZT_GETCONF, &ztc)) {
ast_log(LOG_WARNING, "Error getting conference\n");
close(fd);
goto outrun;
}
if (ztc.confmode) {
/* Whoa, already in a conference... Retry... */
if (!retryzap) {
ast_log(LOG_DEBUG, "Zap channel is in a conference already, retrying with pseudo\n");
retryzap = 1;
goto zapretry;
}
}
memset(&ztc, 0, sizeof(ztc));
/* Add us to the conference */
ztc.chan = 0;
ztc.confno = confno;
ztc.confmode = ZT_CONF_MONITORBOTH;
if (ioctl(fd, ZT_SETCONF, &ztc)) {
ast_log(LOG_WARNING, "Error setting conference\n");
close(fd);
goto outrun;
}
ast_log(LOG_DEBUG, "Placed channel %s in ZAP channel %d monitor\n", chan->name, confno);
for(;;) {
outfd = -1;
ms = -1;
c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms);
if (c) {
if (c->fds[0] != origfd) {
if (retryzap) {
/* Kill old pseudo */
close(fd);
}
ast_log(LOG_DEBUG, "Ooh, something swapped out under us, starting over\n");
retryzap = 0;
goto zapretry;
}
f = ast_read(c);
if (!f)
break;
if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
ret = 0;
break;
} 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);
} else
ast_log(LOG_WARNING, "Huh? Got a non-ulaw (%d) frame in the conference\n", f->subclass);
}
}
ast_frfree(f);
} else if (outfd > -1) {
res = read(outfd, buf, CONF_SIZE);
if (res > 0) {
memset(&fr, 0, sizeof(fr));
fr.frametype = AST_FRAME_VOICE;
fr.subclass = AST_FORMAT_ULAW;
fr.datalen = res;
fr.samples = res;
fr.data = buf;
fr.offset = AST_FRIENDLY_OFFSET;
if (ast_write(chan, &fr) < 0) {
ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno));
/* break; */
}
} else
ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno));
}
}
if (fd != chan->fds[0])
close(fd);
else {
/* Take out of conference */
/* Add us to the conference */
ztc.chan = 0;
ztc.confno = 0;
ztc.confmode = 0;
if (ioctl(fd, ZT_SETCONF, &ztc)) {
ast_log(LOG_WARNING, "Error setting conference\n");
}
}
outrun:
return ret;
}
static int conf_exec(struct ast_channel *chan, void *data)
{
int res=-1;
struct localuser *u;
int retrycnt = 0;
int confflags = 0;
int confno = 0;
char confstr[80];
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);
return 0;
}
}
LOCAL_USER_ADD(u);
if (chan->_state != AST_STATE_UP)
ast_answer(chan);
while(!confno && (++retrycnt < 4)) {
/* Prompt user for conference number */
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)
confno = 0;
}
if (confno) {
/* XXX Should prompt user for pin if pin is required XXX */
/* Run the conference */
res = conf_run(chan, confno, confflags);
}
out:
/* Do the conference */
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, conf_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,243 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Execute an ISDN RAS
*
* 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/module.h>
#include <asterisk/options.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <pthread.h>
/* Need some zaptel help here */
#include <linux/zaptel.h>
static char *tdesc = "Zap RAS Application";
static char *app = "ZapRAS";
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 emulcation is included).\n"
"Your pppd must be patched to be zaptel aware. Arguments should be\n"
"separated by | characters. Always returns -1.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
#define PPP_MAX_ARGS 32
#define PPP_EXEC "/usr/sbin/pppd"
static pid_t spawn_ras(struct ast_channel *chan, char *args)
{
pid_t pid;
int x;
char *c;
char *argv[PPP_MAX_ARGS];
int argc = 0;
char *stringp=NULL;
/* Start by forking */
pid = fork();
if (pid)
return pid;
/* Execute RAS on File handles */
dup2(chan->fds[0], STDIN_FILENO);
/* Close other file descriptors */
for (x=STDERR_FILENO + 1;x<1024;x++)
close(x);
/* Restore original signal handlers */
for (x=0;x<NSIG;x++)
signal(x, SIG_DFL);
/* Reset all arguments */
memset(argv, 0, sizeof(argv));
/* First argument is executable, followed by standard
arguments for zaptel PPP */
argv[argc++] = PPP_EXEC;
argv[argc++] = "nodetach";
/* And all the other arguments */
stringp=args;
c = strsep(&stringp, "|");
while(c && strlen(c) && (argc < (PPP_MAX_ARGS - 4))) {
argv[argc++] = c;
c = strsep(&stringp, "|");
}
argv[argc++] = "plugin";
argv[argc++] = "zaptel.so";
argv[argc++] = "stdin";
#if 0
for (x=0;x<argc;x++) {
fprintf(stderr, "Arg %d: %s\n", x, argv[x]);
}
#endif
/* Finally launch PPP */
execv(PPP_EXEC, argv);
fprintf(stderr, "Failed to exec PPPD!\n");
exit(1);
}
static void run_ras(struct ast_channel *chan, char *args)
{
pid_t pid;
int status;
int res;
int signalled = 0;
struct zt_bufferinfo bi;
int x;
pid = spawn_ras(chan, args);
if (pid < 0) {
ast_log(LOG_WARNING, "Failed to spawn RAS\n");
} else {
for (;;) {
res = wait4(pid, &status, WNOHANG, NULL);
if (!res) {
/* Check for hangup */
if (chan->_softhangup && !signalled) {
ast_log(LOG_DEBUG, "Channel '%s' hungup. Signalling RAS at %d to die...\n", chan->name, pid);
kill(pid, SIGTERM);
signalled=1;
}
/* Try again */
sleep(1);
continue;
}
if (res < 0) {
ast_log(LOG_WARNING, "wait4 returned %d: %s\n", res, strerror(errno));
}
if (option_verbose > 2) {
if (WIFEXITED(status)) {
ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated with status %d\n", chan->name, WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated with signal %d\n",
chan->name, WTERMSIG(status));
} else {
ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated weirdly.\n", chan->name);
}
}
/* Throw back into audio mode */
x = 1;
ioctl(chan->fds[0], ZT_AUDIOMODE, &x);
/* Double check buffering too */
res = ioctl(chan->fds[0], ZT_GET_BUFINFO, &bi);
if (!res) {
/* XXX This is ZAP_BLOCKSIZE XXX */
bi.bufsize = 204;
bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
bi.numbufs = 4;
res = ioctl(chan->fds[0], ZT_SET_BUFINFO, &bi);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set buffer policy on channel %s\n", chan->name);
}
} else
ast_log(LOG_WARNING, "Unable to check buffer policy on channel %s\n", chan->name);
break;
}
}
}
static int zapras_exec(struct ast_channel *chan, void *data)
{
int res=-1;
char args[256];
struct localuser *u;
ZT_PARAMS ztp;
if (!data)
data = "";
LOCAL_USER_ADD(u);
strncpy(args, data, sizeof(args) - 1);
/* Answer the channel if it's not up */
if (chan->_state != AST_STATE_UP)
ast_answer(chan);
if (strcasecmp(chan->type, "Zap")) {
/* If it's not a zap channel, we're done. Wait a couple of
seconds and then hangup... */
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Channel %s is not a Zap channel\n", chan->name);
sleep(2);
} else {
memset(&ztp, 0, sizeof(ztp));
if (ioctl(chan->fds[0], ZT_GET_PARAMS, &ztp)) {
ast_log(LOG_WARNING, "Unable to get zaptel parameters\n");
} else if (ztp.sigtype != ZT_SIG_CLEAR) {
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Channel %s is not a clear channel\n", chan->name);
} else {
/* Everything should be okay. Run PPP. */
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Starting RAS on %s\n", chan->name);
/* Execute RAS */
run_ras(chan, args);
}
}
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, zapras_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,304 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Zap Scanner
*
* Copyright (C) 2003, Digium
*
* Modified from app_zapbarge by David Troy <dave@toad.net>
*
* Mark Spencer <markster@digium.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*
* Special thanks to comphealth.com for sponsoring this
* GPL application.
*/
#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/config.h>
#include <asterisk/app.h>
#include <asterisk/options.h>
#include <asterisk/cli.h>
#include <asterisk/say.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <linux/zaptel.h>
static char *tdesc = "Scan Zap channels application";
static char *app = "ZapScan";
static char *synopsis = "Scan Zap channels to monitor calls";
static char *descrip =
" ZapScan allows a call center manager to monitor\n"
"phone conversations in a convenient way.";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
#define CONF_SIZE 160
static int careful_write(int fd, unsigned char *data, int len)
{
int res;
while(len) {
res = write(fd, data, len);
if (res < 1) {
if (errno != EAGAIN) {
ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno));
return -1;
} else
return 0;
}
len -= res;
data += res;
}
return 0;
}
static int conf_run(struct ast_channel *chan, int confno, int confflags)
{
int fd;
struct zt_confinfo ztc;
struct ast_frame *f;
struct ast_channel *c;
struct ast_frame fr;
int outfd;
int ms;
int nfds;
int res;
int flags;
int retryzap;
int origfd;
int ret = -1;
ZT_BUFFERINFO bi;
char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
char *buf = __buf + AST_FRIENDLY_OFFSET;
/* Set it into U-law mode (write) */
if (ast_set_write_format(chan, AST_FORMAT_ULAW) < 0) {
ast_log(LOG_WARNING, "Unable to set '%s' to write ulaw mode\n", chan->name);
goto outrun;
}
/* Set it into U-law mode (read) */
if (ast_set_read_format(chan, AST_FORMAT_ULAW) < 0) {
ast_log(LOG_WARNING, "Unable to set '%s' to read ulaw mode\n", chan->name);
goto outrun;
}
ast_indicate(chan, -1);
retryzap = strcasecmp(chan->type, "Zap");
zapretry:
origfd = chan->fds[0];
if (retryzap) {
fd = open("/dev/zap/pseudo", O_RDWR);
if (fd < 0) {
ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
goto outrun;
}
/* Make non-blocking */
flags = fcntl(fd, F_GETFL);
if (flags < 0) {
ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno));
close(fd);
goto outrun;
}
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno));
close(fd);
goto outrun;
}
/* Setup buffering information */
memset(&bi, 0, sizeof(bi));
bi.bufsize = CONF_SIZE;
bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
bi.numbufs = 4;
if (ioctl(fd, ZT_SET_BUFINFO, &bi)) {
ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno));
close(fd);
goto outrun;
}
nfds = 1;
} else {
/* XXX Make sure we're not running on a pseudo channel XXX */
fd = chan->fds[0];
nfds = 0;
}
memset(&ztc, 0, sizeof(ztc));
/* Check to see if we're in a conference... */
ztc.chan = 0;
if (ioctl(fd, ZT_GETCONF, &ztc)) {
ast_log(LOG_WARNING, "Error getting conference\n");
close(fd);
goto outrun;
}
if (ztc.confmode) {
/* Whoa, already in a conference... Retry... */
if (!retryzap) {
ast_log(LOG_DEBUG, "Zap channel is in a conference already, retrying with pseudo\n");
retryzap = 1;
goto zapretry;
}
}
memset(&ztc, 0, sizeof(ztc));
/* Add us to the conference */
ztc.chan = 0;
ztc.confno = confno;
ztc.confmode = ZT_CONF_MONITORBOTH;
if (ioctl(fd, ZT_SETCONF, &ztc)) {
ast_log(LOG_WARNING, "Error setting conference\n");
close(fd);
goto outrun;
}
ast_log(LOG_DEBUG, "Placed channel %s in ZAP channel %d monitor\n", chan->name, confno);
for(;;) {
outfd = -1;
ms = -1;
c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms);
if (c) {
if (c->fds[0] != origfd) {
if (retryzap) {
/* Kill old pseudo */
close(fd);
}
ast_log(LOG_DEBUG, "Ooh, something swapped out under us, starting over\n");
retryzap = 0;
goto zapretry;
}
f = ast_read(c);
if (!f)
break;
if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
ret = 0;
break;
} 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);
} else
ast_log(LOG_WARNING, "Huh? Got a non-ulaw (%d) frame in the conference\n", f->subclass);
}
}
ast_frfree(f);
} else if (outfd > -1) {
res = read(outfd, buf, CONF_SIZE);
if (res > 0) {
memset(&fr, 0, sizeof(fr));
fr.frametype = AST_FRAME_VOICE;
fr.subclass = AST_FORMAT_ULAW;
fr.datalen = res;
fr.samples = res;
fr.data = buf;
fr.offset = AST_FRIENDLY_OFFSET;
if (ast_write(chan, &fr) < 0) {
ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno));
/* break; */
}
} else
ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno));
}
}
if (fd != chan->fds[0])
close(fd);
else {
/* Take out of conference */
/* Add us to the conference */
ztc.chan = 0;
ztc.confno = 0;
ztc.confmode = 0;
if (ioctl(fd, ZT_SETCONF, &ztc)) {
ast_log(LOG_WARNING, "Error setting conference\n");
}
}
outrun:
return ret;
}
static int conf_exec(struct ast_channel *chan, void *data)
{
int res=-1;
struct localuser *u;
int confflags = 0;
int confno = 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 (;;) {
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';
}
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;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, conf_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,287 +0,0 @@
/*
* U-law 8-bit audio data
*
* Source: enter.raw
*
* Copyright (C) 1999, Mark Spencer and Linux Support Services
*
* Distributed under the terms of the GNU General Public License
*
*/
static unsigned char enter[] = {
0xba, 0xba, 0xb0, 0xa6, 0xa9, 0xb8, 0xfe, 0x46, 0x42, 0x46,
0x4a, 0xfe, 0xac, 0xa2, 0x9f, 0x9f, 0xa8, 0xb8, 0x3b, 0x29,
0x35, 0x4a, 0xfe, 0xc1, 0xad, 0xa2, 0xad, 0xc5, 0x4e, 0x68,
0x68, 0xe7, 0xb8, 0xb0, 0xb2, 0xc1, 0xc1, 0xb0, 0xae, 0xcd,
0xfe, 0xfe, 0xcd, 0xcd, 0xfe, 0x68, 0xd3, 0xb2, 0xae, 0xab,
0xb2, 0xfe, 0x35, 0x31, 0xdb, 0xac, 0xab, 0xaf, 0xab, 0xaa,
0xb4, 0x68, 0x3b, 0x39, 0x3f, 0x68, 0xb4, 0xa8, 0xa8, 0xb0,
0xbc, 0xbc, 0xc5, 0x3f, 0x31, 0x37, 0xfe, 0xc1, 0xbc, 0xb0,
0xa5, 0xa2, 0xa8, 0xaf, 0xbe, 0x3b, 0x28, 0x26, 0x3d, 0xbc,
0xb0, 0xae, 0xa2, 0x9f, 0xa2, 0xfe, 0x29, 0x24, 0x29, 0x4a,
0xc5, 0xaa, 0xa8, 0xa9, 0xa8, 0xa5, 0xa7, 0xdb, 0x2c, 0x27,
0x2d, 0x4a, 0xfe, 0xdb, 0xb2, 0xa2, 0x9f, 0x9f, 0xae, 0xe7,
0x2c, 0x22, 0x2b, 0xfe, 0xba, 0xb0, 0xaa, 0x9f, 0xa3, 0xb0,
0x5c, 0x33, 0x33, 0x39, 0x5c, 0xdb, 0xc1, 0xb4, 0xb0, 0xaa,
0xad, 0xba, 0x54, 0x46, 0xfe, 0xe7, 0xfe, 0x54, 0xe7, 0xaf,
0xa6, 0xa7, 0xb0, 0xfe, 0x46, 0x39, 0x5c, 0xe7, 0xdb, 0xfe,
0xba, 0xac, 0xa8, 0xc5, 0x46, 0x33, 0x54, 0xc5, 0xae, 0xad,
0xb2, 0xc1, 0xcd, 0xc1, 0xbc, 0xfe, 0x3f, 0x37, 0xfe, 0xb4,
0xb6, 0xcd, 0xdb, 0xc1, 0xb0, 0xb6, 0xcd, 0x4e, 0x39, 0x37,
0xfe, 0xb0, 0xab, 0xa9, 0xa9, 0xa9, 0xb0, 0x5c, 0x29, 0x25,
0x31, 0xfe, 0xc1, 0xb4, 0xae, 0xab, 0xab, 0xb2, 0xcd, 0x3b,
0x2a, 0x2c, 0x54, 0xb4, 0xb4, 0xba, 0xb2, 0xa3, 0x9f, 0xa8,
0xfe, 0x33, 0x27, 0x2a, 0x39, 0xfe, 0xc1, 0xbe, 0xb0, 0xa2,
0x9f, 0xb0, 0x33, 0x22, 0x25, 0x46, 0xc1, 0xb8, 0xb0, 0xab,
0xa8, 0xa8, 0xb0, 0xbe, 0x42, 0x2c, 0x2e, 0x4a, 0xfe, 0x5c,
0xfe, 0xb4, 0xa8, 0xa8, 0xba, 0xfe, 0x4a, 0x39, 0x39, 0x46,
0xfe, 0xbc, 0xaf, 0xa5, 0xa5, 0xae, 0x68, 0x37, 0x4a, 0xfe,
0xfe, 0x4a, 0x4a, 0xd3, 0xb0, 0xb0, 0xc1, 0x5c, 0x46, 0x46,
0xd3, 0xb6, 0xbe, 0x54, 0x54, 0xc9, 0xab, 0xae, 0xc5, 0x46,
0x4a, 0xfe, 0xcd, 0xc9, 0xcd, 0xe7, 0xe7, 0xc9, 0xb4, 0xc5,
0x4a, 0x2c, 0x37, 0xc1, 0xb0, 0xb2, 0xb4, 0xb2, 0xb6, 0xdb,
0xfe, 0x4a, 0x46, 0x3f, 0x68, 0xba, 0xb2, 0xba, 0xc5, 0xb6,
0xb2, 0xcd, 0x33, 0x2e, 0x39, 0x68, 0xfe, 0xe7, 0xba, 0xaf,
0xa7, 0xa7, 0xad, 0xe7, 0x2d, 0x25, 0x2f, 0xd3, 0xbe, 0xcd,
0xc5, 0xac, 0xa6, 0xac, 0xfe, 0x3b, 0x2c, 0x2d, 0x3d, 0xc1,
0xb4, 0xbe, 0xcd, 0xaf, 0xa5, 0xa8, 0xe7, 0x31, 0x2f, 0x39,
0x46, 0x5c, 0xdb, 0xbc, 0xba, 0xaf, 0xa9, 0xad, 0xfe, 0x2f,
0x2d, 0xba, 0xad, 0xba, 0xfe, 0x3d, 0x42, 0x5c, 0xc9, 0xc1,
0xcd, 0xfe, 0xc1, 0xae, 0xa6, 0xcd, 0x33, 0x25, 0x3b, 0xdb,
0xb0, 0xb6, 0xb8, 0xb6, 0xb4, 0xb8, 0xba, 0xfe, 0x3d, 0x37,
0xfe, 0xba, 0xc1, 0x54, 0x54, 0xd3, 0xb0, 0xb4, 0xe7, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xd3, 0xb6, 0xa9, 0xa7, 0xba,
0x3d, 0x35, 0xfe, 0xc1, 0xcd, 0x4a, 0x54, 0xbe, 0xb2, 0xb8,
0xfe, 0x46, 0x3b, 0xfe, 0xba, 0xab, 0xc5, 0x46, 0x3b, 0xbc,
0xaa, 0xab, 0xd3, 0x68, 0xfe, 0xd3, 0xcd, 0xdb, 0x54, 0x3d,
0x4a, 0xbc, 0xac, 0xb4, 0x3f, 0x2e, 0x3d, 0xba, 0xb0, 0xb8,
0xba, 0xb6, 0xba, 0xcd, 0xfe, 0xfe, 0x5c, 0x54, 0xc9, 0xb4,
0xbe, 0x54, 0x54, 0xcd, 0xb6, 0xc9, 0x46, 0x54, 0xcd, 0xc5,
0xdb, 0xfe, 0xfe, 0xc1, 0xae, 0xa9, 0xac, 0xfe, 0x35, 0x2e,
0xfe, 0xba, 0xc1, 0x5c, 0xfe, 0xb6, 0xaa, 0xb0, 0xe7, 0x35,
0x2e, 0x39, 0xc1, 0xac, 0xb0, 0xfe, 0xfe, 0xbc, 0xa6, 0xac,
0xc1, 0x42, 0x46, 0x54, 0xfe, 0xfe, 0xfe, 0xfe, 0xc9, 0xae,
0xa9, 0xb0, 0x54, 0x35, 0x37, 0xfe, 0xd3, 0xd3, 0xb8, 0xae,
0xab, 0xb6, 0xe7, 0xfe, 0xfe, 0x68, 0xfe, 0xfe, 0xfe, 0x4e,
0xfe, 0xb0, 0xac, 0xb8, 0xfe, 0xfe, 0xc1, 0xb6, 0xc5, 0x46,
0x3d, 0xe7, 0xb4, 0xa7, 0xab, 0xbc, 0x3f, 0x37, 0x54, 0xba,
0xcd, 0x54, 0x42, 0xc5, 0xae, 0xac, 0xc9, 0x46, 0x3d, 0x54,
0xba, 0xb0, 0xb0, 0xfe, 0x5c, 0xcd, 0xb0, 0xb0, 0xc9, 0x54,
0x54, 0xfe, 0xfe, 0xfe, 0xfe, 0xe7, 0xcd, 0xc1, 0xba, 0xc5,
0xfe, 0x42, 0x46, 0xfe, 0xc5, 0xba, 0xb2, 0xa7, 0xa7, 0xb0,
0xfe, 0x3d, 0x4a, 0x5c, 0xfe, 0xfe, 0xfe, 0xe7, 0xbc, 0xb0,
0xae, 0xc5, 0x4e, 0x39, 0xfe, 0xc5, 0xbe, 0xfe, 0x54, 0xc9,
0xa9, 0xa2, 0xa5, 0xbc, 0x3b, 0x2f, 0x35, 0xfe, 0xc9, 0xfe,
0xfe, 0xc5, 0xa9, 0xa6, 0xb0, 0x54, 0x31, 0x31, 0x3f, 0xd3,
0xbc, 0xc1, 0xcd, 0xb8, 0xae, 0xa8, 0xb4, 0xd3, 0x54, 0x4e,
0x5c, 0x54, 0xfe, 0xdb, 0xba, 0xb4, 0xb4, 0xba, 0xcd, 0x5c,
0x3d, 0x3f, 0x54, 0xfe, 0xcd, 0xaf, 0xa8, 0xac, 0xc5, 0xfe,
0xfe, 0xe7, 0xdb, 0xfe, 0xfe, 0xfe, 0xe7, 0xb8, 0xaf, 0xb0,
0xe7, 0x42, 0x4a, 0xcd, 0xbc, 0xdb, 0x46, 0x68, 0xcd, 0xb0,
0xab, 0xbc, 0xfe, 0x3d, 0x46, 0xfe, 0xb8, 0xbc, 0xd3, 0xd3,
0xb6, 0xb0, 0xb6, 0x5c, 0x3b, 0x35, 0x54, 0xdb, 0xba, 0xb4,
0xc1, 0xc9, 0xc1, 0xba, 0xc9, 0x5c, 0x3d, 0x46, 0xfe, 0xcd,
0xc5, 0xb8, 0xae, 0xaf, 0xb4, 0xd3, 0x54, 0x3d, 0x35, 0x46,
0xfe, 0xdb, 0xbc, 0xb2, 0xa9, 0xab, 0xba, 0x3f, 0x31, 0x39,
0xfe, 0xe7, 0xdb, 0xcd, 0xb8, 0xae, 0xab, 0xac, 0xe7, 0x3d,
0x2d, 0x3f, 0xfe, 0xdb, 0xfe, 0xfe, 0xbc, 0xaa, 0xa8, 0xb0,
0xfe, 0x31, 0x2d, 0x3d, 0xdb, 0xc5, 0xcd, 0xc9, 0xb4, 0xa8,
0xad, 0xc5, 0x46, 0x39, 0x3f, 0x5c, 0xfe, 0xd3, 0xc5, 0xc1,
0xb6, 0xb0, 0xbc, 0x68, 0x46, 0x4e, 0xe7, 0xfe, 0x5c, 0xfe,
0xc1, 0xaf, 0xb0, 0xb8, 0xe7, 0x5c, 0x5c, 0xfe, 0xe7, 0xfe,
0xfe, 0xe7, 0xb0, 0xab, 0xb2, 0x4a, 0x37, 0x3f, 0xcd, 0xbe,
0xc1, 0xe7, 0xe7, 0xd3, 0xb6, 0xb4, 0xc9, 0x3b, 0x33, 0x4a,
0xba, 0xb4, 0xc5, 0xfe, 0xc9, 0xb6, 0xb4, 0xcd, 0xfe, 0x3b,
0x3b, 0xfe, 0xc1, 0xb6, 0xc5, 0xc5, 0xb8, 0xb0, 0xba, 0x4a,
0x31, 0x35, 0x68, 0xcd, 0xc5, 0xba, 0xb4, 0xb0, 0xb0, 0xba,
0x5c, 0x35, 0x2f, 0x4e, 0xd3, 0xc1, 0xdb, 0xd3, 0xb4, 0xa9,
0xab, 0xcd, 0x3b, 0x2f, 0x35, 0xfe, 0xd3, 0xd3, 0xdb, 0xbc,
0xad, 0xa4, 0xb0, 0xfe, 0x2d, 0x2f, 0x3f, 0xe7, 0xe7, 0xe7,
0xcd, 0xb4, 0xaf, 0xad, 0xc5, 0x3d, 0x31, 0x3d, 0xe7, 0xd3,
0xe7, 0xe7, 0xc1, 0xaf, 0xad, 0xb6, 0xfe, 0x4a, 0x42, 0x54,
0xfe, 0x68, 0xfe, 0xd3, 0xb2, 0xae, 0xb4, 0xfe, 0x42, 0x4e,
0xcd, 0xc5, 0xcd, 0xdb, 0xc9, 0xb4, 0xb0, 0xb6, 0xfe, 0x3b,
0x42, 0xe7, 0xb0, 0xb8, 0xcd, 0xfe, 0xc9, 0xb6, 0xb8, 0xfe,
0x42, 0x3d, 0xfe, 0xc1, 0xb0, 0xba, 0xd3, 0xfe, 0xc1, 0xb0,
0xb6, 0xfe, 0x3b, 0x3f, 0xe7, 0xba, 0xb8, 0xbc, 0xc5, 0xc1,
0xc1, 0xcd, 0xfe, 0x3b, 0x37, 0xfe, 0xc1, 0xb4, 0xb6, 0xb8,
0xb6, 0xb8, 0xc5, 0x5c, 0x3f, 0x46, 0xfe, 0xcd, 0xc5, 0xcd,
0xcd, 0xc1, 0xb2, 0xb2, 0xfe, 0x3f, 0x35, 0x54, 0xdb, 0xc1,
0xcd, 0xcd, 0xbc, 0xaf, 0xac, 0xb6, 0x54, 0x35, 0x31, 0x68,
0xba, 0xb8, 0xcd, 0xdb, 0xc9, 0xb2, 0xb4, 0xc9, 0x46, 0x39,
0x42, 0xdb, 0xbc, 0xbc, 0xcd, 0xcd, 0xbe, 0xb2, 0xb8, 0xe7,
0x54, 0x46, 0xfe, 0xfe, 0xdb, 0xc9, 0xc5, 0xbe, 0xbe, 0xc9,
0xfe, 0x5c, 0x5c, 0xfe, 0xd3, 0xcd, 0xcd, 0xc5, 0xb6, 0xb2,
0xc5, 0x68, 0x4e, 0xfe, 0xc5, 0xc1, 0xcd, 0x68, 0x5c, 0xe7,
0xb8, 0xb6, 0xd3, 0x4a, 0x46, 0xfe, 0xbc, 0xb8, 0xc1, 0xe7,
0xe7, 0xc1, 0xb4, 0xbe, 0xfe, 0x3f, 0x3f, 0xfe, 0xba, 0xb2,
0xba, 0xe7, 0xfe, 0xcd, 0xcd, 0xfe, 0x4e, 0x46, 0xfe, 0xc5,
0xb8, 0xb2, 0xba, 0xc1, 0xcd, 0xd3, 0xe7, 0xfe, 0x5c, 0x5c,
0xfe, 0xe7, 0xc5, 0xbe, 0xb6, 0xba, 0xc5, 0xfe, 0x3f, 0x3f,
0x54, 0xfe, 0xd3, 0xc1, 0xbc, 0xb6, 0xb0, 0xb0, 0xd3, 0x54,
0x39, 0x46, 0xfe, 0xc1, 0xcd, 0xe7, 0xe7, 0xc5, 0xb8, 0xb4,
0xd3, 0x54, 0x37, 0x42, 0xdb, 0xbe, 0xc1, 0xd3, 0xcd, 0xb8,
0xb0, 0xb0, 0xcd, 0x4a, 0x3b, 0x42, 0xe7, 0xc5, 0xbe, 0xcd,
0xe7, 0xd3, 0xc5, 0xcd, 0xfe, 0x54, 0x54, 0x68, 0xe7, 0xc5,
0xc1, 0xc1, 0xcd, 0xcd, 0xc9, 0xc9, 0xcd, 0xe7, 0xfe, 0xfe,
0xfe, 0xe7, 0xc5, 0xbe, 0xc1, 0xfe, 0x5c, 0x5c, 0xfe, 0xcd,
0xcd, 0xcd, 0xdb, 0xd3, 0xc1, 0xbc, 0xbe, 0xfe, 0x4e, 0x54,
0xcd, 0xb6, 0xb8, 0xd3, 0x5c, 0x5c, 0xfe, 0xc5, 0xc9, 0xfe,
0x46, 0x4a, 0xe7, 0xb4, 0xb6, 0xc5, 0xfe, 0xe7, 0xcd, 0xc9,
0xdb, 0xfe, 0x4e, 0x68, 0xd3, 0xb6, 0xb2, 0xbc, 0xfe, 0x68,
0xfe, 0xfe, 0x68, 0x54, 0x68, 0xe7, 0xc5, 0xbc, 0xb8, 0xbe,
0xcd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xd3, 0xd3, 0xcd,
0xc1, 0xb8, 0xbc, 0xdb, 0x4e, 0x42, 0x4a, 0xfe, 0xc9, 0xc1,
0xcd, 0xd3, 0xcd, 0xba, 0xb8, 0xcd, 0x46, 0x3b, 0xfe, 0xc9,
0xba, 0xcd, 0xe7, 0xfe, 0xd3, 0xc1, 0xba, 0xdb, 0x54, 0x3d,
0x68, 0xd3, 0xbc, 0xcd, 0xfe, 0xfe, 0xc5, 0xbe, 0xc1, 0xe7,
0x54, 0x4a, 0xfe, 0xc9, 0xc1, 0xcd, 0xfe, 0xfe, 0xd3, 0xd3,
0xd3, 0xfe, 0xe7, 0xe7, 0xe7, 0xdb, 0xd3, 0xe7, 0xe7, 0xe7,
0xfe, 0xfe, 0xfe, 0xfe, 0xcd, 0xc9, 0xdb, 0xfe, 0xfe, 0xdb,
0xbe, 0xc9, 0xfe, 0x5c, 0xfe, 0xc9, 0xbc, 0xbe, 0xdb, 0x68,
0x5c, 0xdb, 0xc5, 0xd3, 0x54, 0x46, 0xfe, 0xbc, 0xb2, 0xb8,
0xdb, 0x68, 0x68, 0xe7, 0xcd, 0xdb, 0x5c, 0x54, 0xfe, 0xc1,
0xb8, 0xc1, 0xe7, 0xfe, 0xfe, 0xe7, 0xe7, 0xfe, 0xfe, 0xfe,
0xd3, 0xc5, 0xc1, 0xc5, 0xcd, 0xd3, 0xe7, 0xfe, 0x54, 0x4e,
0xfe, 0xd3, 0xcd, 0xd3, 0xd3, 0xc5, 0xc1, 0xc1, 0xe7, 0x5c,
0x4e, 0x5c, 0xd3, 0xc1, 0xcd, 0xfe, 0xfe, 0xcd, 0xba, 0xba,
0xe7, 0x4a, 0x4a, 0x68, 0xcd, 0xc5, 0xcd, 0xfe, 0xfe, 0xcd,
0xb8, 0xc1, 0xe7, 0x4e, 0x5c, 0xe7, 0xc1, 0xc9, 0xdb, 0xfe,
0xe7, 0xc9, 0xc5, 0xd3, 0xfe, 0x68, 0xfe, 0xdb, 0xd3, 0xe7,
0xfe, 0xfe, 0xcd, 0xc9, 0xcd, 0xd3, 0xd3, 0xd3, 0xcd, 0xe7,
0xfe, 0xfe, 0xe7, 0xc5, 0xc5, 0xe7, 0x68, 0x68, 0xe7, 0xc1,
0xc5, 0xfe, 0x5c, 0xfe, 0xd3, 0xc1, 0xd3, 0xfe, 0x68, 0xe7,
0xc5, 0xb6, 0xc5, 0xe7, 0x68, 0xfe, 0xcd, 0xc5, 0xe7, 0xfe,
0x54, 0xfe, 0xc9, 0xc5, 0xdb, 0xfe, 0xfe, 0xfe, 0xd3, 0xd3,
0xfe, 0xfe, 0xfe, 0xcd, 0xc1, 0xc1, 0xc9, 0xd3, 0xd3, 0xe7,
0xfe, 0xfe, 0xfe, 0xfe, 0xe7, 0xd3, 0xdb, 0xe7, 0xe7, 0xd3,
0xcd, 0xd3, 0xfe, 0xfe, 0xfe, 0xcd, 0xc5, 0xd3, 0xe7, 0xe7,
0xc9, 0xbc, 0xbe, 0xe7, 0x68, 0x4a, 0xfe, 0xdb, 0xcd, 0xfe,
0xfe, 0xfe, 0xcd, 0xc1, 0xc9, 0xfe, 0x54, 0x5c, 0xe7, 0xc9,
0xc5, 0xe7, 0xfe, 0xfe, 0xcd, 0xc5, 0xc5, 0xe7, 0xfe, 0xfe,
0xfe, 0xe7, 0xe7, 0xfe, 0xfe, 0xdb, 0xd3, 0xd3, 0xdb, 0xe7,
0xfe, 0xfe, 0xe7, 0xe7, 0xdb, 0xd3, 0xc9, 0xd3, 0xe7, 0xfe,
0xfe, 0xd3, 0xd3, 0xdb, 0xfe, 0xfe, 0xfe, 0xd3, 0xcd, 0xcd,
0xfe, 0xfe, 0xe7, 0xc9, 0xc5, 0xd3, 0xfe, 0xfe, 0xfe, 0xcd,
0xc9, 0xd3, 0xfe, 0xfe, 0xfe, 0xdb, 0xc9, 0xcd, 0xe7, 0xfe,
0xe7, 0xcd, 0xcd, 0xe7, 0xfe, 0xfe, 0xe7, 0xd3, 0xc5, 0xcd,
0xe7, 0xfe, 0xfe, 0xfe, 0xdb, 0xe7, 0xfe, 0xfe, 0xfe, 0xfe,
0xe7, 0xcd, 0xcd, 0xd3, 0xe7, 0xe7, 0xe7, 0xe7, 0xfe, 0xfe,
0xe7, 0xe7, 0xdb, 0xc9, 0xc1, 0xc5, 0xfe, 0x5c, 0x68, 0xfe,
0xd3, 0xdb, 0xe7, 0xe7, 0xe7, 0xd3, 0xc5, 0xcd, 0xe7, 0x68,
0xfe, 0xe7, 0xcd, 0xd3, 0xe7, 0xfe, 0xe7, 0xcd, 0xc1, 0xc1,
0xdb, 0xfe, 0x54, 0xfe, 0xe7, 0xcd, 0xe7, 0xfe, 0xe7, 0xd3,
0xcd, 0xd3, 0xe7, 0xfe, 0xfe, 0xfe, 0xcd, 0xc5, 0xcd, 0xfe,
0xfe, 0xe7, 0xcd, 0xd3, 0xdb, 0xe7, 0xfe, 0xfe, 0xfe, 0xe7,
0xd3, 0xd3, 0xe7, 0xfe, 0xe7, 0xe7, 0xe7, 0xfe, 0xfe, 0xfe,
0xfe, 0xdb, 0xc5, 0xc1, 0xd3, 0xfe, 0xfe, 0xfe, 0xd3, 0xc9,
0xcd, 0xe7, 0xfe, 0xfe, 0xd3, 0xcd, 0xdb, 0xfe, 0x5c, 0xfe,
0xcd, 0xc9, 0xd3, 0xfe, 0xfe, 0xfe, 0xd3, 0xc9, 0xcd, 0xfe,
0x68, 0xfe, 0xd3, 0xc1, 0xc1, 0xdb, 0xfe, 0xfe, 0xe7, 0xe7,
0xfe, 0xfe, 0x68, 0xfe, 0xe7, 0xc5, 0xc9, 0xdb, 0xfe, 0xfe,
0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xdb, 0xc5, 0xc5,
0xd3, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xe7, 0xe7, 0xfe, 0xfe,
0xc9, 0xc1, 0xc5, 0xfe, 0x54, 0x5c, 0xfe, 0xcd, 0xc5, 0xcd,
0xfe, 0xfe, 0xdb, 0xc5, 0xc9, 0xfe, 0x5c, 0x68, 0xfe, 0xcd,
0xcd, 0xfe, 0xfe, 0xfe, 0xe7, 0xc5, 0xc1, 0xd3, 0xfe, 0xfe,
0xdb, 0xc9, 0xc5, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xfe,
0xfe, 0xfe, 0xe7, 0xcd, 0xcd, 0xdb, 0xfe, 0xfe, 0xfe, 0xfe,
0xe7, 0xd3, 0xcd, 0xd3, 0xfe, 0xfe, 0xdb, 0xcd, 0xd3, 0xe7,
0xfe, 0xfe, 0xfe, 0xdb, 0xcd, 0xd3, 0xe7, 0xfe, 0xd3, 0xc5,
0xc9, 0xfe, 0x5c, 0x54, 0xfe, 0xcd, 0xc1, 0xcd, 0xe7, 0xfe,
0xfe, 0xd3, 0xcd, 0xfe, 0x54, 0x5c, 0xe7, 0xc1, 0xc1, 0xd3,
0xfe, 0xfe, 0xe7, 0xd3, 0xd3, 0xe7, 0xfe, 0xfe, 0xfe, 0xcd,
0xc5, 0xcd, 0xd3, 0xe7, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xe7, 0xd3, 0xcd, 0xc9, 0xcd, 0xe7, 0xfe, 0xfe, 0xfe, 0xdb,
0xc9, 0xcd, 0xe7, 0xfe, 0xe7, 0xc9, 0xc5, 0xdb, 0xfe, 0x5c,
0xfe, 0xe7, 0xcd, 0xcd, 0xe7, 0xfe, 0xe7, 0xc5, 0xc1, 0xd3,
0xfe, 0x5c, 0xfe, 0xcd, 0xc5, 0xcd, 0xe7, 0xfe, 0xfe, 0xe7,
0xd3, 0xe7, 0xfe, 0xfe, 0xe7, 0xcd, 0xcd, 0xdb, 0xfe, 0xfe,
0xfe, 0xe7, 0xe7, 0xe7, 0xe7, 0xfe, 0xe7, 0xdb, 0xcd, 0xd3,
0xd3, 0xdb, 0xfe, 0xfe, 0xfe, 0xfe, 0xdb, 0xd3, 0xdb, 0xe7,
0xe7, 0xdb, 0xd3, 0xe7, 0xfe, 0xfe, 0xfe, 0xe7, 0xc9, 0xc5,
0xcd, 0xe7, 0xfe, 0xdb, 0xd3, 0xe7, 0xfe, 0x68, 0xfe, 0xe7,
0xcd, 0xcd, 0xd3, 0xfe, 0xfe, 0xe7, 0xdb, 0xe7, 0xfe, 0x68,
0xfe, 0xdb, 0xfe, 0x68, 0xbe, 0xb2, 0xae, 0xab, 0xb2, 0xfe,
0x2f, 0x31, 0xdb, 0xac, 0xad, 0xaf, 0xab, 0xab, 0xb4, 0x68,
0x37, 0x39, 0x3f, 0xe7, 0xb4, 0xa8, 0xaa, 0xb0, 0xbc, 0xbc,
0xc5, 0x3f, 0x31, 0x3d, 0xfe, 0xc1, 0xb8, 0xb0, 0xa5, 0xa2,
0xa8, 0xaf, 0xdb, 0x3b, 0x28, 0x2a, 0x3d, 0xbc, 0xb0, 0xaa,
0xa2, 0x9f, 0xab, 0xfe, 0x29, 0x24, 0x29, 0x4a, 0xb4, 0xaa,
0xa8, 0xa9, 0xa8, 0xa5, 0xac, 0xdb, 0x2c, 0x27, 0x35, 0x4a,
0xfe, 0xcd, 0xb2, 0xa2, 0x9f, 0x9f, 0xae, 0x4e, 0x2c, 0x22,
0x33, 0xfe, 0xba, 0xb0, 0xa6, 0x9f, 0xa3, 0xbc, 0x5c, 0x33,
0x31, 0x39, 0x5c, 0xcd, 0xc1, 0xb4, 0xad, 0xaa, 0xad, 0xcd,
0x54, 0x46, 0xfe, 0xe7, 0xfe, 0x54, 0xc5, 0xaf, 0xa6, 0xa9,
0xb0, 0xfe, 0x3d, 0x39, 0x5c, 0xdb, 0xdb, 0xfe, 0xba, 0xac,
0xa8, 0xc5, 0x39, 0x33, 0x54, 0xb8, 0xae, 0xad, 0xb8, 0xc1,
0xcd, 0xbe, 0xbc, 0xfe, 0x39, 0x37, 0xfe, 0xb4, 0xba, 0xcd,
0xdb, 0xb8, 0xb0, 0xb6, 0xfe, 0x4e, 0x39, 0x3d, 0xfe, 0xb0,
0xaa, 0xa9, 0xa9, 0xaa, 0xb0, 0x5c, 0x29, 0x28, 0x31, 0xfe,
0xba, 0xb4, 0xae, 0xab, 0xab, 0xb2, 0xfe, 0x3b, 0x2a, 0x2f,
0x54, 0xb4, 0xb4, 0xba, 0xb2, 0xa3, 0x9f, 0xa8, 0xfe, 0x2c,
0x27, 0x2a, 0x46, 0xfe, 0xc1, 0xbc, 0xb0, 0xa2, 0xa2, 0xb0,
0x33, 0x22, 0x2b, 0x46, 0xc1, 0xb4, 0xb0, 0xab, 0xa8, 0xa8,
0xb0, 0xdb, 0x42, 0x2c, 0x33, 0x4a, 0xfe, 0x5c, 0xdb, 0xb4,
0xa8, 0xad, 0xba, 0xfe, 0x46, 0x39, 0x39, 0x4a, 0xfe, 0xbc,
0xab, 0xa5, 0xa5, 0xb8, 0x68, 0x37, 0x4a, 0xe7, 0xfe, 0x4a,
0x5c, 0xd3, 0xb0, 0xb2, 0xc1, 0x5c, 0x42, 0x46, 0xd3, 0xb4,
0xbe, 0x54, 0x54, 0xb6, 0xab, 0xae, 0xe7, 0x46, 0x4a, 0xfe,
0xcd, 0xc9, 0xd3, 0xe7, 0xe7, 0xbe, 0xb4, 0xc5, 0x37, 0x2c,
0x37, 0xc1, 0xb0, 0xb2, 0xb4, 0xb2, 0xb6, 0xdb, 0x54, 0x4a,
0x46, 0x42, 0x68, 0xba, 0xb2, 0xba, 0xc5, 0xb6, 0xb6, 0xcd,
0x33, 0x2f, 0x39, 0x68, 0xfe, 0xe7, 0xba, 0xac, 0xa7, 0xa7,
0xb2, 0xe7, 0x2d, 0x25, 0x2f, 0xd3, 0xbe, 0xd3, 0xc5, 0xac,
0xa6, 0xac, 0xfe, 0x33, 0x2c, 0x2d, 0x54, 0xc1, 0xb4, 0xcd,
0xcd, 0xaf, 0xa4, 0xa8, 0xe7, 0x31, 0x31, 0x39, 0x46, 0xfe,
0xdb, 0xbc, 0xb6, 0xaf, 0xa9, 0xb2, 0xfe, 0x2f, 0xfe, 0xba,
0xad, 0xba, 0x4e, 0x3d, 0x42, 0xfe, 0xc9, 0xc1, 0xe7, 0xfe,
0xc1, 0xa9, 0xa6, 0xcd, 0x2a, 0x25, 0x3b, 0xbc, 0xb0, 0xb6,
0xb8, 0xb4, 0xb4, 0xb8, 0xc1, 0xfe, 0x3d, 0x3d, 0xfe, 0xba,
0xd3, 0x54, 0x54, 0xbe, 0xb0, 0xb4, 0xe7, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xc5, 0xb6, 0xa9, 0xaa, 0xba, 0x3d, 0x39,
0xfe, 0xc1, 0xfe, 0x4a, 0x54, 0xbe, 0xb2, 0xb8, 0xfe, 0x3d,
0x3b, 0xfe, 0xb0, 0xab, 0xc5, 0x39, 0x3b, 0xbc, 0xa7, 0xab,
0xd3, 0x68, 0xfe, 0xd3, 0xcd, 0xfe, 0x54, 0x3d, 0xfe, 0xbc,
0xac, 0xc9, 0x3f, 0x2e, 0xfe, 0xba, 0xb0, 0xba, 0xba, 0xb6,
0xba, 0xd3, 0xfe, 0xfe, 0x5c, 0x54, 0xc9, 0xb4, 0xbe, 0x54,
0x68, 0xcd, 0xb6, 0xfe, 0x46, 0x54, 0xcd, 0xc5, 0xdb, 0xfe,
0xe7, 0xc1, 0xae, 0xa8, 0xac, 0xfe, 0x2e, 0x2e, 0xfe, 0xb6,
0xc1, 0x5c, 0xe7, 0xb6, 0xaa, 0xb0, 0x54, 0x35, 0x2e, 0x4a,
0xc1, 0xac, 0xbc, 0xfe, 0xfe, 0xaf, 0xa6, 0xac, 0xfe, 0x42,
0x46, 0x5c, 0xfe, 0xfe, 0xfe, 0xe7, 0xc9, 0xae, 0xa9, 0xb0,
0x54, 0x31, 0x37, 0xfe, 0xd3, 0xd3, 0xb8, 0xac, 0xab, 0xb6,
0xe7, 0xfe, 0xfe, 0x68, 0xfe, 0xfe, 0xfe, 0x54, 0xfe, 0xb0,
0xae, 0xb8, 0xfe, 0xe7, 0xc1, 0xb6, 0xe7, 0x46, 0x3d, 0xe7,
0xae, 0xa7, 0xab, 0xdb, 0x3f, 0x37, 0xfe, 0xba, 0xcd, 0x3f,
0x42, 0xc5, 0xab, 0xac, 0xc9, 0x46, 0x3d, 0x54, 0xba, 0xad,
0xb0, 0xfe, 0x68, 0xcd, 0xb0, 0xb0, 0xc9, 0x54, 0x54, 0xfe,
0xfe, 0xfe, 0xfe, 0xe7, 0xcd, 0xbe, 0xba, 0xc5, 0x68, 0x42,
0x46, 0xe7, 0xc5, 0xba, 0xaf, 0xa7, 0xa7, 0xbc, 0xfe, 0x3d,
0x4a, 0x68, 0xfe, 0xfe, 0xfe, 0xe7, 0xbc, 0xaf, 0xae, 0xc5,
0x3d, 0x39, 0xfe, 0xbc, 0xbe, 0xfe, 0x68, 0xc9, 0xa9, 0xa2,
0xaa, 0xbc, 0x3b, 0x2d, 0x35, 0xfe, 0xcd, 0xfe, 0xfe, 0xb4,
0xa9, 0xa6, 0xbc, 0x54, 0x31, 0x31, 0x54, 0xd3, 0xbc, 0xc5,
0xcd, 0xb8, 0xab, 0xa8, 0xb4, 0xfe, 0x54, 0x4e, 0x68, 0x54,
0xfe, 0xc9, 0xba, 0xb4, 0xb4, 0xba, 0xcd, 0x5c, 0x3b, 0x3f,
0x54, 0xfe, 0xcd, 0xaf, 0xa8, 0xac, 0xc5, 0x68, 0xfe, 0xe7,
0xdb, 0xfe, 0xfe, 0xfe, 0xcd, 0xb8, 0xaf, 0xb6, 0xe7, 0x42,
0x5c, 0xcd, 0xbc, 0xfe, 0x46, 0x68, 0xba, 0xb0, 0xab, 0xbc,
0x54, 0x3d, 0x46, 0xc9, 0xb8, 0xbc, 0xdb, 0xd3, 0xb6, 0xb0,
0xb6, 0x5c, 0x37, 0x35, 0x54, 0xc9, 0xba, 0xb4, 0xc1, 0xc9,
0xc1, 0xba, 0xe7, 0x5c, 0x3d, 0x54, 0xfe, 0xcd, 0xc5, 0xb8,
0xae, 0xaf, 0xb4, 0xd3, 0x54, 0x3b, 0x35, 0x46, 0xfe, 0xdb,
0xbc, 0xaf, 0xa9, 0xab, 0xd3, 0x3f, 0x31, 0x3f, 0xfe, 0xe7,
0xdb, 0xcd, 0xb8, 0xae, 0xaa, 0xac, 0xe7, 0x33, 0x2d, 0x3f,
0xd3, 0xdb, 0xfe, 0xfe, 0xbc, 0xaa, 0xa9, 0xb0, 0xfe, 0x31,
0x2f, 0x3d, 0xdb, 0xc5, 0xcd, 0xc9, 0xae, 0xa8, 0xad, 0xfe,
0x46, 0x39, 0x46, 0x5c, 0xfe, 0xcd, 0xc5, 0xc1, 0xb6, 0xb0,
0xbc, 0x68, 0x42, 0x4e, 0xe7, 0xfe, 0x5c, 0xfe, 0xb6, 0xaf,
0xb0, 0xc5, 0xe7, 0x5c, 0x5c, 0xfe, 0xe7, 0xfe, 0x68, 0xe7,
0xb0, 0xac, 0xb2, 0x4a, 0x35, 0x3f, 0xcd, 0xbc, 0xc1, 0xe7,
0xe7, 0xd3, 0xb6, 0xb4, 0xfe, 0x3b, 0x33, 0xfe, 0xba, 0xb4,
0xd3, 0xfe, 0xc9, 0xb4, 0xb4, 0xcd, 0x4a, 0x3b, 0x3b, 0xfe,
0xb8, 0xb6, 0xc5, 0xc5, 0xb8, 0xb0, 0xcd, 0x4a, 0x31, 0x3b,
0x68, 0xcd, 0xc1, 0xba, 0xb4, 0xb0, 0xb0, 0xba, 0x5c, 0x2f,
0x2f, 0x4e, 0xc9, 0xc1, 0xdb, 0xc9, 0xb4 };

View File

@@ -1,207 +0,0 @@
/*
* U-law 8-bit audio data
*
* Source: leave.raw
*
* Copyright (C) 1999, Mark Spencer and Linux Support Services
*
* Distributed under the terms of the GNU General Public License
*
*/
static unsigned char leave[] = {
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xc1, 0x3d,
0x42, 0x46, 0x3f, 0x3f, 0x46, 0x3f, 0x4e, 0xba, 0xbe, 0xbe,
0xbc, 0xba, 0xbe, 0xc5, 0xb6, 0x2e, 0x2c, 0x33, 0x2f, 0x2e,
0x2f, 0x33, 0x2b, 0x54, 0xac, 0xb0, 0xb0, 0xad, 0xaf, 0xb0,
0xae, 0xcd, 0x3b, 0x2f, 0x31, 0x2e, 0x2f, 0x31, 0x2e, 0x46,
0xc5, 0xaf, 0xb0, 0xaf, 0xae, 0xaf, 0xaf, 0xb0, 0xfe, 0x2d,
0x31, 0x31, 0x2e, 0x31, 0x2f, 0x31, 0xfe, 0xae, 0xaf, 0xaf,
0xae, 0xb0, 0xae, 0xaf, 0xfe, 0xdb, 0x2e, 0x2e, 0x31, 0x31,
0x2d, 0x2e, 0xdb, 0x68, 0xaf, 0xad, 0xb0, 0xb0, 0xae, 0xaf,
0x5c, 0xe7, 0x39, 0x2d, 0x31, 0x31, 0x31, 0x2d, 0xfe, 0xfe,
0x68, 0xad, 0xaf, 0xb0, 0xaf, 0xac, 0xbc, 0xfe, 0xd3, 0x2f,
0x2e, 0x33, 0x31, 0x2d, 0x4e, 0xdb, 0xfe, 0xfe, 0xac, 0xaf,
0xb0, 0xac, 0xb6, 0x68, 0xe7, 0xdb, 0x2e, 0x2f, 0x35, 0x2f,
0x31, 0xe7, 0xe7, 0x68, 0xad, 0xac, 0xb0, 0xae, 0xac, 0xfe,
0xfe, 0xdb, 0xfe, 0x2d, 0x33, 0x31, 0x2e, 0xfe, 0xfe, 0xfe,
0xfe, 0xbc, 0xaf, 0xb0, 0xad, 0xfe, 0xfe, 0xfe, 0xe7, 0x5c,
0x2e, 0x33, 0x2e, 0x35, 0xe7, 0xfe, 0xfe, 0xfe, 0xad, 0xb0,
0xaf, 0xc1, 0xfe, 0xe7, 0xfe, 0xe7, 0x3d, 0x31, 0x2f, 0x37,
0xe7, 0xfe, 0xfe, 0xe7, 0xfe, 0xaf, 0xad, 0xbe, 0xfe, 0xdb,
0xfe, 0xfe, 0xdb, 0x35, 0x2d, 0x39, 0xdb, 0xfe, 0xfe, 0xdb,
0xfe, 0xfe, 0xad, 0xaf, 0xfe, 0xfe, 0xe7, 0x68, 0xfe, 0xd3,
0x2e, 0x2c, 0xdb, 0xdb, 0x2c, 0x35, 0xd3, 0x68, 0xaf, 0xad,
0xb0, 0xb0, 0xad, 0xba, 0x68, 0xe7, 0xe7, 0x2e, 0x2f, 0x33,
0x31, 0x2d, 0xdb, 0xd3, 0x5c, 0xae, 0xaa, 0xe7, 0x68, 0xaa,
0xe7, 0xfe, 0xdb, 0xe7, 0xfe, 0xe7, 0xd3, 0x2d, 0xfe, 0xdb,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xc5, 0xfe, 0xe7, 0xe7,
0xfe, 0xfe, 0xe7, 0xe7, 0x3b, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xe7, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xc5, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xe7, 0xfe, 0x3b,
0xdb, 0xfe, 0xfe, 0xfe, 0xe7, 0xfe, 0xfe, 0xb0, 0xfe, 0xfe,
0xe7, 0xfe, 0xfe, 0xfe, 0xdb, 0x2e, 0x5c, 0xdb, 0xfe, 0xfe,
0xe7, 0xe7, 0x68, 0xb0, 0xbe, 0x68, 0xe7, 0xe7, 0xfe, 0xfe,
0xdb, 0x39, 0x2f, 0xdb, 0xfe, 0xfe, 0xe7, 0xe7, 0xfe, 0xbe,
0xaf, 0xe7, 0x68, 0xe7, 0xfe, 0xfe, 0xfe, 0xfe, 0x33, 0x33,
0xdb, 0xfe, 0xfe, 0xdb, 0xe7, 0xfe, 0xb0, 0xb0, 0xfe, 0xfe,
0xe7, 0xfe, 0xfe, 0xfe, 0x35, 0x33, 0xe7, 0xe7, 0xfe, 0xe7,
0xe7, 0xfe, 0xb0, 0xb2, 0xb0, 0xfe, 0xfe, 0xe7, 0xfe, 0xe7,
0x46, 0x35, 0x35, 0x3f, 0xe7, 0xfe, 0xe7, 0xfe, 0xb2, 0xb0,
0xb2, 0xb0, 0xfe, 0xfe, 0xfe, 0xfe, 0x42, 0x35, 0x37, 0x33,
0xe7, 0xfe, 0xfe, 0xfe, 0xb8, 0xb0, 0xb6, 0xb0, 0xba, 0xfe,
0xfe, 0xe7, 0xe7, 0x33, 0x39, 0x39, 0x33, 0xe7, 0xdb, 0xfe,
0xe7, 0xb0, 0xb4, 0xb6, 0xb0, 0xcd, 0xfe, 0xe7, 0xe7, 0x33,
0x39, 0x3b, 0x33, 0x46, 0xd3, 0xfe, 0xfe, 0xb0, 0xb2, 0xb6,
0xb4, 0xb0, 0xfe, 0xfe, 0xdb, 0x35, 0x37, 0x39, 0x39, 0x35,
0x37, 0xdb, 0x68, 0xcd, 0xb2, 0xb6, 0xb6, 0xb4, 0xb4, 0x68,
0xe7, 0x42, 0x37, 0x3b, 0x3b, 0x39, 0x37, 0xdb, 0xfe, 0xcd,
0xb2, 0xb6, 0xb6, 0xb6, 0xb2, 0xb4, 0xfe, 0x54, 0x37, 0x3b,
0x39, 0x3b, 0x3b, 0x39, 0xe7, 0xfe, 0xb6, 0xb6, 0xb6, 0xb4,
0xb6, 0xb6, 0xbc, 0xfe, 0x3f, 0x3b, 0x3b, 0x39, 0x3b, 0x3b,
0x39, 0xe7, 0xb6, 0xb8, 0xb8, 0xb6, 0xb8, 0xb8, 0xb4, 0xfe,
0x3b, 0x3d, 0x3d, 0x3b, 0x39, 0x3d, 0x3b, 0x39, 0xbe, 0xb8,
0xba, 0xb8, 0xb6, 0xb8, 0xba, 0xb4, 0xfe, 0x39, 0x3f, 0x3d,
0x3b, 0x3d, 0x3f, 0x39, 0xdb, 0xb4, 0xba, 0xb8, 0xb6, 0xb8,
0xbc, 0xb4, 0xba, 0x39, 0x42, 0x3f, 0x3d, 0x3d, 0x3f, 0x3f,
0x3b, 0xb8, 0xb6, 0xbc, 0xb8, 0xb8, 0xba, 0xbc, 0xb8, 0xe7,
0x3d, 0x42, 0x3f, 0x3d, 0x3f, 0x42, 0x3d, 0xfe, 0xb8, 0xbc,
0xbc, 0xba, 0xba, 0xbc, 0xba, 0xe7, 0x3d, 0x3f, 0x42, 0x3f,
0x3f, 0x42, 0x42, 0xfe, 0xfe, 0xbc, 0xbc, 0xbe, 0xbc, 0xbe,
0xbc, 0xc5, 0xe7, 0x68, 0x42, 0x46, 0x42, 0x46, 0x42, 0x46,
0xfe, 0xfe, 0xbc, 0xbe, 0xbe, 0xbe, 0xbc, 0xc5, 0xfe, 0xdb,
0x46, 0x46, 0x4a, 0x4a, 0x46, 0x46, 0xe7, 0xfe, 0xd3, 0xbe,
0xc9, 0xc9, 0xc5, 0xc5, 0xe7, 0xdb, 0xd3, 0x4a, 0x4e, 0x54,
0x4e, 0x4e, 0xfe, 0x5c, 0x54, 0xd3, 0xcd, 0xd3, 0xd3, 0xcd,
0xd3, 0xd3, 0xcd, 0xfe, 0x5c, 0x68, 0x5c, 0x5c, 0x5c, 0x68,
0x5c, 0x5c, 0xcd, 0xcd, 0xd3, 0xcd, 0xdb, 0xe7, 0xe7, 0xdb,
0xe7, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xe7,
0xfe, 0x5c, 0x5c, 0xfe, 0xfe, 0xfe, 0xfe, 0x46, 0x35, 0x35,
0x37, 0x39, 0x3b, 0x39, 0x35, 0x33, 0x35, 0x5c, 0xd3, 0xcd,
0xdb, 0xfe, 0xfe, 0xd3, 0xb0, 0xb0, 0xb0, 0xb4, 0xb4, 0xb6,
0xb2, 0xb0, 0xb0, 0xb6, 0xcd, 0x5c, 0x68, 0xfe, 0xfe, 0xfe,
0x3b, 0x33, 0x35, 0x37, 0x39, 0x3b, 0x39, 0x37, 0x35, 0x35,
0x3f, 0xdb, 0xcd, 0xcd, 0xdb, 0xfe, 0xe7, 0xc5, 0xb0, 0xb0,
0xb2, 0xb6, 0xb6, 0xb6, 0xb2, 0xb0, 0xb0, 0xcd, 0x5c, 0x5c,
0xfe, 0xe7, 0xe7, 0xfe, 0x35, 0x35, 0x35, 0x39, 0x3b, 0x3b,
0x39, 0x35, 0x33, 0x39, 0xdb, 0xcd, 0xd3, 0xe7, 0xfe, 0xfe,
0xba, 0xb0, 0xb0, 0xb2, 0xb4, 0xb6, 0xb6, 0xb4, 0xb2, 0xb0,
0xb4, 0xc9, 0x5c, 0x68, 0xfe, 0xfe, 0x5c, 0x3b, 0x35, 0x37,
0x39, 0x3b, 0x3b, 0x3b, 0x39, 0x37, 0x37, 0x3d, 0xe7, 0xcd,
0xdb, 0xfe, 0xe7, 0xbe, 0xb2, 0xb2, 0xb4, 0xb4, 0xb6, 0xb6,
0xb6, 0xb4, 0xb0, 0xb0, 0xc5, 0x5c, 0x5c, 0xfe, 0xe7, 0xe7,
0x4e, 0x35, 0x35, 0x37, 0x3b, 0x3b, 0x3b, 0x39, 0x37, 0x37,
0x3b, 0xe7, 0xc9, 0xcd, 0xe7, 0xfe, 0xd3, 0xb4, 0xb2, 0xb2,
0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb4, 0xb2, 0xb4, 0xc1, 0x68,
0x68, 0xfe, 0xfe, 0x42, 0x39, 0x37, 0x39, 0x3b, 0x3b, 0x3b,
0x3b, 0x3b, 0x39, 0x37, 0x3b, 0xfe, 0xd3, 0xdb, 0xfe, 0xcd,
0xb4, 0xb2, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb4, 0xb2,
0xb2, 0xc1, 0x5c, 0x5c, 0xfe, 0xfe, 0xfe, 0x3d, 0x37, 0x37,
0x39, 0x3b, 0x3b, 0x3b, 0x3b, 0x37, 0x37, 0x39, 0xfe, 0xcd,
0xd3, 0xfe, 0xfe, 0xc1, 0xb2, 0xb2, 0xb4, 0xb6, 0xb6, 0xb6,
0xb6, 0xb6, 0xb6, 0xb4, 0xb4, 0xbc, 0x68, 0xfe, 0xfe, 0xfe,
0x3b, 0x39, 0x39, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x39,
0x39, 0x3b, 0xfe, 0xdb, 0xe7, 0xfe, 0xbc, 0xb6, 0xb6, 0xb6,
0xb8, 0xb6, 0xb6, 0xb6, 0xb8, 0xb6, 0xb4, 0xb4, 0xbc, 0xfe,
0x68, 0xfe, 0xe7, 0x5c, 0x3b, 0x39, 0x39, 0x3b, 0x3b, 0x3b,
0x3d, 0x3d, 0x3b, 0x39, 0x3b, 0x68, 0xdb, 0xdb, 0xfe, 0xe7,
0xb8, 0xb6, 0xb6, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb6,
0xb4, 0xb6, 0xdb, 0x68, 0xfe, 0xfe, 0x46, 0x3b, 0x3b, 0x3b,
0x3d, 0x3d, 0x3b, 0x3d, 0x3d, 0x3d, 0x3d, 0x3b, 0x3b, 0x5c,
0xdb, 0xdb, 0xc9, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xbc, 0xcd, 0xfe, 0xfe, 0x3d,
0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3b, 0x3d, 0x3d, 0x3d, 0x3d,
0x3b, 0x3d, 0x46, 0xfe, 0xe7, 0xe7, 0xc5, 0xb8, 0xb8, 0xb8,
0xba, 0xba, 0xb8, 0xb8, 0xba, 0xba, 0xb8, 0xb8, 0xb8, 0xcd,
0xfe, 0xfe, 0x68, 0x3f, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d,
0x3d, 0x3d, 0x3f, 0x3f, 0x3d, 0x3b, 0x4a, 0xfe, 0xdb, 0xbc,
0xb8, 0xba, 0xba, 0xba, 0xba, 0xb8, 0xb8, 0xb8, 0xba, 0xba,
0xba, 0xba, 0xba, 0xc5, 0xfe, 0x54, 0x3f, 0x3f, 0x3f, 0x3f,
0x3f, 0x3f, 0x3d, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x42,
0xfe, 0xe7, 0xdb, 0xbc, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
0xba, 0xba, 0xbc, 0xba, 0xba, 0xba, 0xc5, 0xfe, 0xfe, 0x4e,
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x42,
0x42, 0x42, 0x3f, 0x46, 0xfe, 0xcd, 0xb8, 0xba, 0xbc, 0xbc,
0xbc, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xba, 0xb8,
0xbe, 0xfe, 0x42, 0x3d, 0x3f, 0x42, 0x42, 0x42, 0x3f, 0x3f,
0x3f, 0x42, 0x42, 0x42, 0x42, 0x3f, 0x3f, 0x68, 0xdb, 0xc5,
0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xba, 0xba, 0xba, 0xbc, 0xbc,
0xbc, 0xbc, 0xba, 0xc1, 0xfe, 0xfe, 0x3f, 0x42, 0x46, 0x46,
0x46, 0x42, 0x42, 0x42, 0x42, 0x42, 0x46, 0x46, 0x42, 0x3f,
0x42, 0x68, 0xbe, 0xba, 0xbc, 0xbe, 0xbe, 0xbe, 0xbc, 0xbc,
0xbc, 0xbc, 0xbe, 0xc1, 0xbe, 0xbc, 0xba, 0xbe, 0x68, 0x3f,
0x42, 0x46, 0x4a, 0x4a, 0x46, 0x42, 0x42, 0x42, 0x46, 0x46,
0x46, 0x46, 0x42, 0x42, 0x68, 0xd3, 0xbc, 0xbc, 0xbe, 0xc1,
0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc1, 0xbe, 0xbe,
0xc1, 0xfe, 0x4e, 0x42, 0x46, 0x4a, 0x4a, 0x4a, 0x46, 0x46,
0x46, 0x46, 0x4a, 0x4a, 0x4a, 0x46, 0x46, 0x68, 0xdb, 0xbe,
0xbe, 0xc1, 0xc5, 0xc1, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xc1,
0xc5, 0xc5, 0xbe, 0xbc, 0xc1, 0x4e, 0x46, 0x46, 0x4a, 0x4e,
0x4e, 0x4a, 0x46, 0x46, 0x46, 0x4a, 0x4a, 0x4e, 0x4a, 0x46,
0x46, 0xfe, 0xbe, 0xbe, 0xc1, 0xc9, 0xc5, 0xc5, 0xc1, 0xc1,
0xc1, 0xc1, 0xc5, 0xc5, 0xc5, 0xc5, 0xbe, 0xc1, 0xfe, 0x4a,
0x4a, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4a, 0x4a, 0x4a, 0x4e,
0x54, 0x4e, 0x4a, 0x4a, 0x4e, 0xcd, 0xc1, 0xc5, 0xc5, 0xc9,
0xc5, 0xc5, 0xc5, 0xc5, 0xc9, 0xcd, 0xcd, 0xcd, 0xcd, 0xc9,
0xc9, 0xd3, 0x68, 0x54, 0x5c, 0x68, 0x68, 0x68, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x68, 0x68, 0x5c, 0x54, 0x5c, 0xdb, 0xcd,
0xcd, 0xdb, 0xdb, 0xdb, 0xdb, 0xd3, 0xd3, 0xe7, 0xe7, 0xe7,
0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xe7, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe };

View File

@@ -1,739 +0,0 @@
%{
/* Written by Pace Willisson (pace@blitz.com)
* and placed in the public domain.
*
* Largely rewritten by J.T. Conklin (jtc@wimsey.com)
*
* $FreeBSD: src/bin/expr/expr.y,v 1.16 2000/07/22 10:59:36 se Exp $
*/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <regex.h>
#include <limits.h>
#include <asterisk/ast_expr.h>
#include <asterisk/logger.h>
# if ! defined(QUAD_MIN)
# define QUAD_MIN (-0x7fffffffffffffffL-1)
# endif
# if ! defined(QUAD_MAX)
# define QUAD_MAX (0x7fffffffffffffffL)
# endif
#define YYPARSE_PARAM kota
#define YYLEX_PARAM kota
/* #define ast_log fprintf
#define LOG_WARNING stderr */
enum valtype {
integer, numeric_string, string
} ;
struct val {
enum valtype type;
union {
char *s;
quad_t i;
} u;
} ;
struct parser_control {
struct val *result;
int pipa;
char *argv;
char *ptrptr;
int firsttoken;
} ;
static int chk_div __P((quad_t, quad_t));
static int chk_minus __P((quad_t, quad_t, quad_t));
static int chk_plus __P((quad_t, quad_t, quad_t));
static int chk_times __P((quad_t, quad_t, quad_t));
static void free_value __P((struct val *));
static int is_zero_or_null __P((struct val *));
static int isstring __P((struct val *));
static struct val *make_integer __P((quad_t));
static struct val *make_str __P((const char *));
static struct val *op_and __P((struct val *, struct val *));
static struct val *op_colon __P((struct val *, struct val *));
static struct val *op_div __P((struct val *, struct val *));
static struct val *op_eq __P((struct val *, struct val *));
static struct val *op_ge __P((struct val *, struct val *));
static struct val *op_gt __P((struct val *, struct val *));
static struct val *op_le __P((struct val *, struct val *));
static struct val *op_lt __P((struct val *, struct val *));
static struct val *op_minus __P((struct val *, struct val *));
static struct val *op_ne __P((struct val *, struct val *));
static struct val *op_or __P((struct val *, struct val *));
static struct val *op_plus __P((struct val *, struct val *));
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 *));
static int ast_yyerror __P((const char *));
%}
%pure-parser
/* %name-prefix="ast_yy" */
%union
{
struct val *val;
}
%{
static int ast_yylex __P((YYSTYPE *, struct parser_control *));
%}
%left <val> '|'
%left <val> '&'
%left <val> '=' '>' '<' GE LE NE
%left <val> '+' '-'
%left <val> '*' '/' '%'
%left <val> ':'
%token <val> TOKEN
%type <val> start expr
%%
start: expr { ((struct parser_control *)kota)->result = $$; }
;
expr: TOKEN
| '(' 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); }
;
%%
static struct val *
make_integer (i)
quad_t i;
{
struct val *vp;
vp = (struct val *) malloc (sizeof (*vp));
if (vp == NULL) {
ast_log(LOG_WARNING, "malloc() failed\n");
return(NULL);
}
vp->type = integer;
vp->u.i = i;
return vp;
}
static struct val *
make_str (s)
const char *s;
{
struct val *vp;
size_t i;
int isint;
vp = (struct val *) malloc (sizeof (*vp));
if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
ast_log(LOG_WARNING,"malloc() failed\n");
return(NULL);
}
for(i = 1, isint = isdigit(s[0]) || s[0] == '-';
isint && i < strlen(s);
i++)
{
if(!isdigit(s[i]))
isint = 0;
}
if (isint)
vp->type = numeric_string;
else
vp->type = string;
return vp;
}
static void
free_value (vp)
struct val *vp;
{
if (vp==NULL) {
return;
}
if (vp->type == string || vp->type == numeric_string)
free (vp->u.s);
}
static quad_t
to_integer (vp)
struct val *vp;
{
quad_t i;
if (vp == NULL) {
ast_log(LOG_WARNING,"vp==NULL in to_integer()\n");
return(0);
}
if (vp->type == integer)
return 1;
if (vp->type == string)
return 0;
/* vp->type == numeric_string, make it numeric */
errno = 0;
i = strtoq(vp->u.s, (char**)NULL, 10);
if (errno != 0) {
free(vp->u.s);
ast_log(LOG_WARNING,"overflow\n");
return(0);
}
free (vp->u.s);
vp->u.i = i;
vp->type = integer;
return 1;
}
static void
to_string (vp)
struct val *vp;
{
char *tmp;
if (vp->type == string || vp->type == numeric_string)
return;
tmp = malloc ((size_t)25);
if (tmp == NULL) {
ast_log(LOG_WARNING,"malloc() failed\n");
return;
}
sprintf (tmp, "%lld", (long long)vp->u.i);
vp->type = string;
vp->u.s = tmp;
}
static int
isstring (vp)
struct val *vp;
{
/* only TRUE if this string is not a valid integer */
return (vp->type == string);
}
static int
ast_yylex (YYSTYPE *lvalp, struct parser_control *karoto)
{
char *p;
if (karoto->firsttoken==1) {
p=strtok_r(karoto->argv," ",&(karoto->ptrptr));
karoto->firsttoken=0;
} else {
p=strtok_r(NULL," ",&(karoto->ptrptr));
}
if (p==NULL) {
return (0);
}
if (strlen (p) == 1) {
if (strchr ("|&=<>+-*/%:()", *p))
return (*p);
} else if (strlen (p) == 2 && p[1] == '=') {
switch (*p) {
case '>': return (GE);
case '<': return (LE);
case '!': return (NE);
}
}
lvalp->val = make_str (p);
return (TOKEN);
}
static int
is_zero_or_null (vp)
struct val *vp;
{
if (vp->type == integer) {
return (vp->u.i == 0);
} else {
return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0));
}
/* NOTREACHED */
}
char *ast_expr (char *arg)
{
struct parser_control karoto;
char *kota;
char *pirouni;
kota=strdup(arg);
karoto.result = NULL;
karoto.firsttoken=1;
karoto.argv=kota;
ast_yyparse ((void *)&karoto);
free(kota);
if (karoto.result==NULL) {
pirouni=strdup("0");
return(pirouni);
} else {
if (karoto.result->type == integer) {
pirouni=malloc(256);
sprintf (pirouni,"%lld", (long long)karoto.result->u.i);
}
else {
pirouni=strdup(karoto.result->u.s);
}
free(karoto.result);
}
return(pirouni);
}
#ifdef STANDALONE
int main(int argc,char **argv) {
char *s;
s=ast_expr(argv[1]);
printf("=====%s======\n",s);
}
#endif
static int
ast_yyerror (s)
const char *s;
{
ast_log(LOG_WARNING,"ast_yyerror(): syntax error: %s\n",s);
return(0);
}
static struct val *
op_or (a, b)
struct val *a, *b;
{
if (is_zero_or_null (a)) {
free_value (a);
return (b);
} else {
free_value (b);
return (a);
}
}
static struct val *
op_and (a, b)
struct val *a, *b;
{
if (is_zero_or_null (a) || is_zero_or_null (b)) {
free_value (a);
free_value (b);
return (make_integer ((quad_t)0));
} else {
free_value (b);
return (a);
}
}
static struct val *
op_eq (a, b)
struct val *a, *b;
{
struct val *r;
if (isstring (a) || isstring (b)) {
to_string (a);
to_string (b);
r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) == 0));
} else {
(void)to_integer(a);
(void)to_integer(b);
r = make_integer ((quad_t)(a->u.i == b->u.i));
}
free_value (a);
free_value (b);
return r;
}
static struct val *
op_gt (a, b)
struct val *a, *b;
{
struct val *r;
if (isstring (a) || isstring (b)) {
to_string (a);
to_string (b);
r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) > 0));
} else {
(void)to_integer(a);
(void)to_integer(b);
r = make_integer ((quad_t)(a->u.i > b->u.i));
}
free_value (a);
free_value (b);
return r;
}
static struct val *
op_lt (a, b)
struct val *a, *b;
{
struct val *r;
if (isstring (a) || isstring (b)) {
to_string (a);
to_string (b);
r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) < 0));
} else {
(void)to_integer(a);
(void)to_integer(b);
r = make_integer ((quad_t)(a->u.i < b->u.i));
}
free_value (a);
free_value (b);
return r;
}
static struct val *
op_ge (a, b)
struct val *a, *b;
{
struct val *r;
if (isstring (a) || isstring (b)) {
to_string (a);
to_string (b);
r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) >= 0));
} else {
(void)to_integer(a);
(void)to_integer(b);
r = make_integer ((quad_t)(a->u.i >= b->u.i));
}
free_value (a);
free_value (b);
return r;
}
static struct val *
op_le (a, b)
struct val *a, *b;
{
struct val *r;
if (isstring (a) || isstring (b)) {
to_string (a);
to_string (b);
r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) <= 0));
} else {
(void)to_integer(a);
(void)to_integer(b);
r = make_integer ((quad_t)(a->u.i <= b->u.i));
}
free_value (a);
free_value (b);
return r;
}
static struct val *
op_ne (a, b)
struct val *a, *b;
{
struct val *r;
if (isstring (a) || isstring (b)) {
to_string (a);
to_string (b);
r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) != 0));
} else {
(void)to_integer(a);
(void)to_integer(b);
r = make_integer ((quad_t)(a->u.i != b->u.i));
}
free_value (a);
free_value (b);
return r;
}
static int
chk_plus (a, b, r)
quad_t a, b, r;
{
/* sum of two positive numbers must be positive */
if (a > 0 && b > 0 && r <= 0)
return 1;
/* sum of two negative numbers must be negative */
if (a < 0 && b < 0 && r >= 0)
return 1;
/* all other cases are OK */
return 0;
}
static struct val *
op_plus (a, b)
struct val *a, *b;
{
struct val *r;
if (!to_integer (a) || !to_integer (b)) {
ast_log(LOG_WARNING,"non-numeric argument\n");
free_value(a);
free_value(b);
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);
return r;
}
static int
chk_minus (a, b, r)
quad_t a, b, r;
{
/* special case subtraction of QUAD_MIN */
if (b == QUAD_MIN) {
if (a >= 0)
return 1;
else
return 0;
}
/* this is allowed for b != QUAD_MIN */
return chk_plus (a, -b, r);
}
static struct val *
op_minus (a, b)
struct val *a, *b;
{
struct val *r;
if (!to_integer (a) || !to_integer (b)) {
free_value(a);
free_value(b);
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)) {
free_value(a);
free_value(b);
ast_log(LOG_WARNING, "overload\n");
return(NULL);
}
free_value (a);
free_value (b);
return r;
}
static int
chk_times (a, b, r)
quad_t a, b, r;
{
/* special case: first operand is 0, no overflow possible */
if (a == 0)
return 0;
/* cerify that result of division matches second operand */
if (r / a != b)
return 1;
return 0;
}
static struct val *
op_times (a, b)
struct val *a, *b;
{
struct val *r;
if (!to_integer (a) || !to_integer (b)) {
free_value(a);
free_value(b);
ast_log(LOG_WARNING, "non-numeric argument\n");
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);
return (r);
}
static int
chk_div (a, b)
quad_t a, b;
{
/* div by zero has been taken care of before */
/* only QUAD_MIN / -1 causes overflow */
if (a == QUAD_MIN && b == -1)
return 1;
/* everything else is OK */
return 0;
}
static struct val *
op_div (a, b)
struct val *a, *b;
{
struct val *r;
if (!to_integer (a) || !to_integer (b)) {
free_value(a);
free_value(b);
ast_log(LOG_WARNING, "non-numeric argument\n");
return(NULL);
}
if (b->u.i == 0) {
ast_log(LOG_WARNING, "division by zero\n");
free_value(a);
free_value(b);
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);
return r;
}
static struct val *
op_rem (a, b)
struct val *a, *b;
{
struct val *r;
if (!to_integer (a) || !to_integer (b)) {
ast_log(LOG_WARNING, "non-numeric argument\n");
free_value(a);
free_value(b);
return(NULL);
}
if (b->u.i == 0) {
ast_log(LOG_WARNING, "div by zero\n");
free_value(a);
free_value(b);
return(NULL);
}
r = make_integer (/*(quad_t)*/(a->u.i % b->u.i));
/* chk_rem necessary ??? */
free_value (a);
free_value (b);
return r;
}
static struct val *
op_colon (a, b)
struct val *a, *b;
{
regex_t rp;
regmatch_t rm[2];
char errbuf[256];
int eval;
struct val *v;
/* coerce to both arguments to strings */
to_string(a);
to_string(b);
/* compile regular expression */
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(NULL);
}
/* compare string against pattern */
/* remember that patterns are anchored to the beginning of the line */
if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 && rm[0].rm_so == 0) {
if (rm[1].rm_so >= 0) {
*(a->u.s + rm[1].rm_eo) = '\0';
v = make_str (a->u.s + rm[1].rm_so);
} else {
v = make_integer ((quad_t)(rm[0].rm_eo - rm[0].rm_so));
}
} else {
if (rp.re_nsub == 0) {
v = make_integer ((quad_t)0);
} else {
v = make_str ("");
}
}
/* free arguments and pattern buffer */
free_value (a);
free_value (b);
regfree (&rp);
return v;
}

View File

@@ -1,32 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* General Definitions for Asterisk top level program
*
* 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
*/
#ifndef _ASTCONF_H
#define _ASTCONF_H
#define AST_CONFIG_MAX_PATH 255
extern char ast_config_AST_CONFIG_DIR[AST_CONFIG_MAX_PATH];
extern char ast_config_AST_CONFIG_FILE[AST_CONFIG_MAX_PATH];
extern char ast_config_AST_MODULE_DIR[AST_CONFIG_MAX_PATH];
extern char ast_config_AST_SPOOL_DIR[AST_CONFIG_MAX_PATH];
extern char ast_config_AST_VAR_DIR[AST_CONFIG_MAX_PATH];
extern char ast_config_AST_LOG_DIR[AST_CONFIG_MAX_PATH];
extern char ast_config_AST_AGI_DIR[AST_CONFIG_MAX_PATH];
extern char ast_config_AST_DB[AST_CONFIG_MAX_PATH];
extern char ast_config_AST_KEY_DIR[AST_CONFIG_MAX_PATH];
extern char ast_config_AST_PID[AST_CONFIG_MAX_PATH];
extern char ast_config_AST_SOCKET[AST_CONFIG_MAX_PATH];
extern char ast_config_AST_RUN_DIR[AST_CONFIG_MAX_PATH];
#endif

161
asterisk-ng-doxygen Normal file
View File

@@ -0,0 +1,161 @@
# Here's the doxygen configuration file for the asterisk source
# code
# Doxygen configuration generated by Doxywizard version 0.1
#---------------------------------------------------------------------------
# General configuration options
#---------------------------------------------------------------------------
PROJECT_NAME = Asterisk
PROJECT_NUMBER = 0.1.8
OUTPUT_DIRECTORY = doc/
OUTPUT_LANGUAGE = English
EXTRACT_ALL = YES
EXTRACT_PRIVATE = NO
EXTRACT_STATIC = NO
HIDE_UNDOC_MEMBERS = YES
HIDE_UNDOC_CLASSES = NO
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ALWAYS_DETAILED_SEC = NO
FULL_PATH_NAMES = NO
STRIP_FROM_PATH =
INTERNAL_DOCS = NO
CLASS_DIAGRAMS = YES
SOURCE_BROWSER = YES
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
VERBATIM_HEADERS = YES
SHOW_INCLUDE_FILES = YES
JAVADOC_AUTOBRIEF = NO
INHERIT_DOCS = YES
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
DISTRIBUTE_GROUP_DOC = YES
TAB_SIZE = 4
ENABLED_SECTIONS =
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = NO
ALIASES =
MAX_INITIALIZER_LINES = 30
OPTIMIZE_OUTPUT_FOR_C = NO
SHOW_USED_FILES = YES
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = .
FILE_PATTERNS = *.h \
*.c
RECURSIVE = YES
EXCLUDE =
EXCLUDE_PATTERNS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS =
IMAGE_PATH =
INPUT_FILTER =
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = NO
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = NO
GENERATE_CHI = NO
BINARY_TOC = NO
TOC_EXPAND = NO
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NO
TREEVIEW_WIDTH = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = YES
LATEX_OUTPUT = ps
COMPACT_LATEX = NO
PAPER_TYPE = a4
EXTRA_PACKAGES =
LATEX_HEADER =
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = YES
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = NO
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
#---------------------------------------------------------------------------
# Configuration::addtions related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
HAVE_DOT = NO
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
GRAPHICAL_HIERARCHY = YES
DOT_PATH =
MAX_DOT_GRAPH_WIDTH = 1024
MAX_DOT_GRAPH_HEIGHT = 1024
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE = NO
CGI_NAME = search.cgi
CGI_URL = http://localhost/cgi-bin
DOC_URL = http://localhost/asterisk/documentation
DOC_ABSPATH = /var/www/html/asterisk/documentation
BIN_ABSPATH = /usr/local/bin
EXT_DOC_PATHS =

1156
asterisk.c

File diff suppressed because it is too large Load Diff

View File

@@ -16,20 +16,15 @@
#define DEFAULT_LANGUAGE "en"
#define AST_CONFIG_MAX_PATH 255
#define AST_CONFIG_DIR ASTETCDIR
#define AST_RUN_DIR ASTVARRUNDIR
#define AST_SOCKET ASTVARRUNDIR "/asterisk.ctl"
#define AST_PID ASTVARRUNDIR "/asterisk.pid"
#define AST_MODULE_DIR ASTMODDIR
#define AST_SPOOL_DIR ASTSPOOLDIR
#define AST_VAR_DIR ASTVARLIBDIR
#define AST_LOG_DIR ASTLOGDIR
#define AST_AGI_DIR ASTAGIDIR
#define AST_KEY_DIR ASTVARLIBDIR "/keys"
#define AST_DB ASTVARLIBDIR "/astdb"
#define AST_CONFIG_DIR "/etc/asterisk"
#define AST_SOCKET "/var/run/asterisk.ctl"
#define AST_MODULE_DIR "/usr/lib/asterisk/modules"
#define AST_SPOOL_DIR "/var/spool/asterisk"
#define AST_VAR_DIR "/var/lib/asterisk"
#define AST_LOG_DIR "/var/log/asterisk"
#define AST_AGI_DIR "/var/lib/asterisk/agi-bin"
#define AST_CONFIG_FILE ASTCONFPATH
#define AST_CONFIG_FILE "asterisk.conf"
#define AST_SOUNDS AST_VAR_DIR "/sounds"
#define AST_IMAGES AST_VAR_DIR "/images"
@@ -42,11 +37,4 @@ extern int load_pbx(void);
extern int init_logger(void);
/* Provided by frame.c */
extern int init_framer(void);
/* Provided by logger.c */
extern int reload_logger(int);
/* Provided by term.c */
extern int term_init(void);
/* Provided by db.c */
extern int astdb_init(void);
#endif

View File

@@ -1,32 +0,0 @@
#
# Don't use ast mm routines
#
CFLAGS+=-DNO_AST_MM
TARGET=$(shell if [ -f /usr/include/newt.h ]; then echo "astman"; else echo "none" ; fi)
all: depend $(TARGET)
install:
if [ "$(TARGET)" != "none" ]; then \
for x in $(TARGET); do \
install -m 755 $$x $(DESTDIR)$(ASTSBINDIR)/astman; \
done ; \
fi
none:
@echo Not building the Asterisk Manager "astman"
clean:
rm -f *.o astman .depend
astman: astman.o ../md5.o
$(CC) -o astman astman.o ../md5.o -lnewt
ifneq ($(wildcard .depend),)
include .depend
endif
depend: .depend
.depend:
../mkdep $(CFLAGS) `ls *.c`

View File

@@ -1,680 +0,0 @@
/*
* ASTerisk MANager
* Copyright (C) 2002, Linux Support Services, Inc.
*
* Distributed under the terms of the GNU General Public License
*/
#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/select.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <asterisk/md5.h>
#include <asterisk/manager.h>
#define MAX_HEADERS 80
#define MAX_LEN 256
static struct ast_mansession {
struct sockaddr_in sin;
int fd;
char inbuf[MAX_LEN];
int inlen;
} session;
static struct ast_chan {
char name[80];
char exten[20];
char context[20];
char priority[20];
char callerid[40];
char state[10];
struct ast_chan *next;
} *chans;
static struct ast_chan *find_chan(char *name)
{
struct ast_chan *prev = NULL, *chan = chans;
while(chan) {
if (!strcmp(name, chan->name))
return chan;
prev = chan;
chan = chan->next;
}
chan = malloc(sizeof(struct ast_chan));
if (chan) {
memset(chan, 0, sizeof(struct ast_chan));
strncpy(chan->name, name, sizeof(chan->name) - 1);
if (prev)
prev->next = chan;
else
chans = chan;
}
return chan;
}
static void del_chan(char *name)
{
struct ast_chan *prev = NULL, *chan = chans;
while(chan) {
if (!strcmp(name, chan->name)) {
if (prev)
prev->next = chan->next;
else
chans = chan->next;
return;
}
prev = chan;
chan = chan->next;
}
}
static void fdprintf(int fd, char *fmt, ...)
{
char stuff[4096];
va_list ap;
va_start(ap, fmt);
vsnprintf(stuff, sizeof(stuff), fmt, ap);
va_end(ap);
write(fd, stuff, strlen(stuff));
}
static char *get_header(struct message *m, char *var)
{
char cmp[80];
int x;
snprintf(cmp, sizeof(cmp), "%s: ", var);
for (x=0;x<m->hdrcount;x++)
if (!strncasecmp(cmp, m->headers[x], strlen(cmp)))
return m->headers[x] + strlen(cmp);
return "";
}
static int event_newstate(struct ast_mansession *s, struct message *m)
{
struct ast_chan *chan;
chan = find_chan(get_header(m, "Channel"));
strncpy(chan->state, get_header(m, "State"), sizeof(chan->state) - 1);
return 0;
}
static int event_newexten(struct ast_mansession *s, struct message *m)
{
struct ast_chan *chan;
chan = find_chan(get_header(m, "Channel"));
strncpy(chan->exten, get_header(m, "Extension"), sizeof(chan->exten) - 1);
strncpy(chan->context, get_header(m, "Context"), sizeof(chan->context) - 1);
strncpy(chan->priority, get_header(m, "Priority"), sizeof(chan->priority) - 1);
return 0;
}
static int event_newchannel(struct ast_mansession *s, struct message *m)
{
struct ast_chan *chan;
chan = find_chan(get_header(m, "Channel"));
strncpy(chan->state, get_header(m, "State"), sizeof(chan->state) - 1);
strncpy(chan->callerid, get_header(m, "Callerid"), sizeof(chan->callerid) - 1);
return 0;
}
static int event_status(struct ast_mansession *s, struct message *m)
{
struct ast_chan *chan;
chan = find_chan(get_header(m, "Channel"));
strncpy(chan->state, get_header(m, "State"), sizeof(chan->state) - 1);
strncpy(chan->callerid, get_header(m, "Callerid"), sizeof(chan->callerid) - 1);
strncpy(chan->exten, get_header(m, "Extension"), sizeof(chan->exten) - 1);
strncpy(chan->context, get_header(m, "Context"), sizeof(chan->context) - 1);
strncpy(chan->priority, get_header(m, "Priority"), sizeof(chan->priority) - 1);
return 0;
}
static int event_hangup(struct ast_mansession *s, struct message *m)
{
del_chan(get_header(m, "Channel"));
return 0;
}
static int event_ignore(struct ast_mansession *s, struct message *m)
{
return 0;
}
static int event_rename(struct ast_mansession *s, struct message *m)
{
struct ast_chan *chan;
chan = find_chan(get_header(m, "Oldname"));
strncpy(chan->name, get_header(m, "Newname"), sizeof(chan->name) - 1);
return 0;
}
static struct event {
char *event;
int (*func)(struct ast_mansession *s, struct message *m);
} events[] = {
{ "Newstate", event_newstate },
{ "Newchannel", event_newchannel },
{ "Newexten", event_newexten },
{ "Hangup", event_hangup },
{ "Rename", event_rename },
{ "Status", event_status },
{ "Link", event_ignore },
{ "Unlink", 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));
if (!strlen(event)) {
fprintf(stderr, "Missing event in request");
return 0;
}
for (x=0;x<sizeof(events) / sizeof(events[0]);x++) {
if (!strcasecmp(event, events[x].event)) {
if (events[x].func(s, m))
return -1;
break;
}
}
if (x >= sizeof(events) / sizeof(events[0]))
fprintf(stderr, "Ignoring unknown event '%s'", event);
#if 0
for (x=0;x<m->hdrcount;x++) {
printf("Header: %s\n", m->headers[x]);
}
#endif
return 0;
}
static void rebuild_channels(newtComponent c)
{
void *prev = NULL;
struct ast_chan *chan;
char tmpn[42];
char tmp[256];
int x=0;
prev = newtListboxGetCurrent(c);
newtListboxClear(c);
chan = chans;
while(chan) {
snprintf(tmpn, sizeof(tmpn), "%s (%s)", chan->name, chan->callerid);
if (strlen(chan->exten))
snprintf(tmp, sizeof(tmp), "%-30s %8s -> %s@%s:%s",
tmpn, chan->state,
chan->exten, chan->context, chan->priority);
else
snprintf(tmp, sizeof(tmp), "%-30s %8s",
tmpn, chan->state);
newtListboxAppendEntry(c, tmp, chan);
x++;
chan = chan->next;
}
if (!x)
newtListboxAppendEntry(c, " << No Active Channels >> ", NULL);
newtListboxSetCurrentByKey(c, prev);
}
static int has_input(struct ast_mansession *s)
{
int x;
for (x=1;x<s->inlen;x++)
if ((s->inbuf[x] == '\n') && (s->inbuf[x-1] == '\r'))
return 1;
return 0;
}
static int get_input(struct ast_mansession *s, char *output)
{
/* output must have at least sizeof(s->inbuf) space */
int res;
int x;
struct timeval tv = {0, 0};
fd_set fds;
for (x=1;x<s->inlen;x++) {
if ((s->inbuf[x] == '\n') && (s->inbuf[x-1] == '\r')) {
/* Copy output data up to and including \r\n */
memcpy(output, s->inbuf, x + 1);
/* Add trailing \0 */
output[x+1] = '\0';
/* Move remaining data back to the front */
memmove(s->inbuf, s->inbuf + x + 1, s->inlen - x);
s->inlen -= (x + 1);
return 1;
}
}
if (s->inlen >= sizeof(s->inbuf) - 1) {
fprintf(stderr, "Dumping long line with no return from %s: %s\n", inet_ntoa(s->sin.sin_addr), s->inbuf);
s->inlen = 0;
}
FD_ZERO(&fds);
FD_SET(s->fd, &fds);
res = select(s->fd + 1, &fds, NULL, NULL, &tv);
if (res < 0) {
fprintf(stderr, "Select returned error: %s\n", strerror(errno));
} else if (res > 0) {
res = read(s->fd, s->inbuf + s->inlen, sizeof(s->inbuf) - 1 - s->inlen);
if (res < 1)
return -1;
s->inlen += res;
s->inbuf[s->inlen] = '\0';
} else {
return 2;
}
return 0;
}
static int input_check(struct ast_mansession *s, struct message **mout)
{
static struct message m;
int res;
if (mout)
*mout = NULL;
for(;;) {
res = get_input(s, m.headers[m.hdrcount]);
if (res == 1) {
#if 0
fprintf(stderr, "Got header: %s", m.headers[m.hdrcount]);
fgetc(stdin);
#endif
/* Strip trailing \r\n */
if (strlen(m.headers[m.hdrcount]) < 2)
continue;
m.headers[m.hdrcount][strlen(m.headers[m.hdrcount]) - 2] = '\0';
if (!strlen(m.headers[m.hdrcount])) {
if (mout && strlen(get_header(&m, "Response"))) {
*mout = &m;
return 0;
}
if (process_message(s, &m))
break;
memset(&m, 0, sizeof(&m));
} else if (m.hdrcount < MAX_HEADERS - 1)
m.hdrcount++;
} else if (res < 0) {
return -1;
} else if (res == 2)
return 0;
}
return -1;
}
static struct message *wait_for_response(int timeout)
{
struct message *m;
struct timeval tv;
int res;
fd_set fds;
for (;;) {
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
FD_SET(session.fd, &fds);
res = select(session.fd + 1, &fds, NULL, NULL, &tv);
if (res < 1)
break;
if (input_check(&session, &m) < 0) {
return NULL;
}
if (m)
return m;
}
return NULL;
}
static int manager_action(char *action, char *fmt, ...)
{
struct ast_mansession *s;
char tmp[4096];
va_list ap;
s = &session;
fdprintf(s->fd, "Action: %s\r\n", action);
va_start(ap, fmt);
vsnprintf(tmp, sizeof(tmp), fmt, ap);
va_end(ap);
write(s->fd, tmp, strlen(tmp));
fdprintf(s->fd, "\r\n");
return 0;
}
static int show_message(char *title, char *msg)
{
newtComponent form;
newtComponent label;
newtComponent ok;
struct newtExitStruct es;
newtCenteredWindow(60,7, title);
label = newtLabel(4,1,msg);
ok = newtButton(27, 3, "OK");
form = newtForm(NULL, NULL, 0);
newtFormAddComponents(form, label, ok, NULL);
newtFormRun(form, &es);
newtPopWindow();
newtFormDestroy(form);
return 0;
}
static newtComponent showform;
static int show_doing(char *title, char *tmp)
{
struct newtExitStruct es;
newtComponent label;
showform = newtForm(NULL, NULL, 0);
newtCenteredWindow(70,4, title);
label = newtLabel(3,1,tmp);
newtFormAddComponents(showform,label, NULL);
newtFormSetTimer(showform, 200);
newtFormRun(showform, &es);
return 0;
}
static int hide_doing(void)
{
newtPopWindow();
newtFormDestroy(showform);
return 0;
}
static void try_status(void)
{
struct message *m;
manager_action("Status", "");
m = wait_for_response(10000);
if (!m) {
show_message("Status Failed", "Timeout waiting for response");
} else if (strcasecmp(get_header(m, "Response"), "Success")) {
show_message("Status Failed Failed", get_header(m, "Message"));
}
}
static void try_hangup(newtComponent c)
{
struct ast_chan *chan;
struct message *m;
chan = newtListboxGetCurrent(c);
if (chan) {
manager_action("Hangup", "Channel: %s\r\n", chan->name);
m = wait_for_response(10000);
if (!m) {
show_message("Hangup Failed", "Timeout waiting for response");
} else if (strcasecmp(get_header(m, "Response"), "Success")) {
show_message("Hangup Failed", get_header(m, "Message"));
}
}
}
static int get_user_input(char *msg, char *buf, int buflen)
{
newtComponent form;
newtComponent ok;
newtComponent cancel;
newtComponent inpfield;
char *input;
int res = -1;
struct newtExitStruct es;
newtCenteredWindow(60,7, msg);
inpfield = newtEntry(5, 2, "", 50, &input, 0);
ok = newtButton(22, 3, "OK");
cancel = newtButton(32, 3, "Cancel");
form = newtForm(NULL, NULL, 0);
newtFormAddComponents(form, inpfield, ok, cancel, NULL);
newtFormRun(form, &es);
strncpy(buf, input, buflen - 1);
if (es.u.co == ok)
res = 0;
else
res = -1;
newtPopWindow();
newtFormDestroy(form);
return res;
}
static void try_redirect(newtComponent c)
{
struct ast_chan *chan;
char dest[256];
struct message *m;
char channame[256];
char tmp[80];
char *context;
chan = newtListboxGetCurrent(c);
if (chan) {
strncpy(channame, chan->name, sizeof(channame) - 1);
snprintf(tmp, sizeof(tmp), "Enter new extension for %s", channame);
if (get_user_input(tmp, dest, sizeof(dest)))
return;
if ((context = strchr(dest, '@'))) {
*context = '\0';
context++;
manager_action("Redirect", "Channel: %s\r\nContext: %s\r\nExten: %s\r\nPriority: 1\r\n", chan->name,context,dest);
} else {
manager_action("Redirect", "Channel: %s\r\nExten: %s\r\nPriority: 1\r\n", chan->name, dest);
}
m = wait_for_response(10000);
if (!m) {
show_message("Hangup Failed", "Timeout waiting for response");
} else if (strcasecmp(get_header(m, "Response"), "Success")) {
show_message("Hangup Failed", get_header(m, "Message"));
}
}
}
static int manage_calls(char *host)
{
newtComponent form;
newtComponent quit;
newtComponent hangup;
newtComponent redirect;
newtComponent channels;
struct newtExitStruct es;
char tmp[80];
/* If there's one thing you learn from this code, it is this...
Never, ever fly Air France. Their customer service is absolutely
the worst. I've never heard the words "That's not my problem" as
many times as I have from their staff -- It should, without doubt
be their corporate motto if it isn't already. Don't bother giving
them business because you're just a pain in their side and they
will be sure to let you know the first time you speak to them.
If you ever want to make me happy just tell me that you, too, will
never fly Air France again either (in spite of their excellent
cuisine). */
snprintf(tmp, sizeof(tmp), "Asterisk Manager at %s", host);
newtCenteredWindow(74, 20, tmp);
form = newtForm(NULL, NULL, 0);
newtFormWatchFd(form, session.fd, NEWT_FD_READ);
newtFormSetTimer(form, 100);
quit = newtButton(62, 16, "Quit");
redirect = newtButton(35, 16, "Redirect");
hangup = newtButton(50, 16, "Hangup");
channels = newtListbox(1,1,14, NEWT_FLAG_SCROLL);
newtFormAddComponents(form, channels, redirect, hangup, quit, NULL);
newtListboxSetWidth(channels, 72);
show_doing("Getting Status", "Retrieving system status...");
try_status();
hide_doing();
for(;;) {
newtFormRun(form, &es);
if (has_input(&session) || (es.reason == NEWT_EXIT_FDREADY)) {
if (input_check(&session, NULL)) {
show_message("Disconnected", "Disconnected from remote host");
break;
}
} else if (es.reason == NEWT_EXIT_COMPONENT) {
if (es.u.co == quit)
break;
if (es.u.co == hangup) {
try_hangup(channels);
} else if (es.u.co == redirect) {
try_redirect(channels);
}
}
rebuild_channels(channels);
}
newtFormDestroy(form);
return 0;
}
static int login(char *hostname)
{
newtComponent form;
newtComponent cancel;
newtComponent login;
newtComponent username;
newtComponent password;
newtComponent label;
newtComponent ulabel;
newtComponent plabel;
char *user;
char *pass;
struct message *m;
struct newtExitStruct es;
char tmp[55];
struct hostent *hp;
int res = -1;
session.fd = socket(AF_INET, SOCK_STREAM, 0);
if (session.fd < 0) {
snprintf(tmp, sizeof(tmp), "socket() failed: %s\n", strerror(errno));
show_message("Socket failed", tmp);
return -1;
}
snprintf(tmp, sizeof(tmp), "Looking up %s\n", hostname);
show_doing("Connecting....", tmp);
hp = gethostbyname(hostname);
if (!hp) {
snprintf(tmp, sizeof(tmp), "No such address: %s\n", hostname);
show_message("Host lookup failed", tmp);
return -1;
}
hide_doing();
snprintf(tmp, sizeof(tmp), "Connecting to %s", hostname);
show_doing("Connecting...", tmp);
session.sin.sin_family = AF_INET;
session.sin.sin_port = htons(DEFAULT_MANAGER_PORT);
memcpy(&session.sin.sin_addr, hp->h_addr, sizeof(session.sin.sin_addr));
if (connect(session.fd,(struct sockaddr*)&session.sin, sizeof(session.sin))) {
snprintf(tmp, sizeof(tmp), "%s failed: %s\n", hostname, strerror(errno));
show_message("Connect Failed", tmp);
return -1;
}
hide_doing();
login = newtButton(5, 6, "Login");
cancel = newtButton(25, 6, "Cancel");
newtCenteredWindow(40, 10, "Asterisk Manager Login");
snprintf(tmp, sizeof(tmp), "Host: %s", hostname);
label = newtLabel(4,1, tmp);
ulabel = newtLabel(4,2,"Username:");
plabel = newtLabel(4,3,"Password:");
username = newtEntry(14, 2, "", 20, &user, 0);
password = newtEntry(14, 3, "", 20, &pass, NEWT_FLAG_HIDDEN);
form = newtForm(NULL, NULL, 0);
newtFormAddComponents(form, username, password, login, cancel, label, ulabel, plabel,NULL);
newtFormRun(form, &es);
if (es.reason == NEWT_EXIT_COMPONENT) {
if (es.u.co == login) {
snprintf(tmp, sizeof(tmp), "Logging in '%s'...", user);
show_doing("Logging in", tmp);
/* Check to see if the remote host supports MD5 Authentication */
manager_action("Challenge", "AuthType: MD5\r\n");
m = wait_for_response(10000);
if (m && !strcasecmp(get_header(m, "Response"), "Success")) {
char *challenge = get_header(m, "Challenge");
int x;
int len = 0;
char md5key[256] = "";
struct MD5Context md5;
unsigned char digest[16];
MD5Init(&md5);
MD5Update(&md5, challenge, strlen(challenge));
MD5Update(&md5, pass, strlen(pass));
MD5Final(digest, &md5);
for (x=0; x<16; x++)
len += sprintf(md5key + len, "%2.2x", digest[x]);
manager_action("Login",
"AuthType: MD5\r\n"
"Username: %s\r\n"
"Key: %s\r\n",
user, md5key);
m = wait_for_response(10000);
hide_doing();
if (!strcasecmp(get_header(m, "Response"), "Success")) {
res = 0;
} else {
show_message("Login Failed", get_header(m, "Message"));
}
} else {
memset(m, 0, sizeof(m));
manager_action("Login",
"Username: %s\r\n"
"Secret: %s\r\n",
user, pass);
m = wait_for_response(10000);
hide_doing();
if (m) {
if (!strcasecmp(get_header(m, "Response"), "Success")) {
res = 0;
} else {
show_message("Login Failed", get_header(m, "Message"));
}
}
}
}
}
newtFormDestroy(form);
return res;
}
int main(int argc, char *argv[])
{
if (argc < 2) {
fprintf(stderr, "Usage: astman <host>\n");
exit(1);
}
newtInit();
newtCls();
newtDrawRootText(0, 0, "Asterisk Manager (C)2002, Linux Support Services, Inc.");
newtPushHelpLine("Welcome to the Asterisk Manager!");
if (login(argv[1])) {
newtFinished();
exit(1);
}
manage_calls(argv[1]);
newtFinished();
return 0;
}

368
astmm.c
View File

@@ -1,368 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Channel Variables
*
* Copyright (C) 2002, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#ifdef __AST_DEBUG_MALLOC
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <asterisk/cli.h>
#include <asterisk/logger.h>
#include <asterisk/options.h>
#include <asterisk/lock.h>
#define SOME_PRIME 563
#define FUNC_CALLOC 1
#define FUNC_MALLOC 2
#define FUNC_REALLOC 3
#define FUNC_STRDUP 4
#define FUNC_STRNDUP 5
#define FUNC_VASPRINTF 6
/* Undefine all our macros */
#undef malloc
#undef calloc
#undef realloc
#undef strdup
#undef strndup
#undef free
#undef vasprintf
static FILE *mmlog;
static struct ast_region {
struct ast_region *next;
char file[40];
char func[40];
int lineno;
int which;
size_t len;
unsigned char data[0];
} *regions[SOME_PRIME];
#define HASH(a) \
(((unsigned long)(a)) % SOME_PRIME)
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)
{
struct ast_region *reg;
void *ptr=NULL;
int hash;
reg = malloc(size + sizeof(struct ast_region));
ast_mutex_lock(&reglock);
if (reg) {
strncpy(reg->file, file, sizeof(reg->file) - 1);
reg->file[sizeof(reg->file) - 1] = '\0';
strncpy(reg->func, func, sizeof(reg->func) - 1);
reg->func[sizeof(reg->func) - 1] = '\0';
reg->lineno = lineno;
reg->len = size;
reg->which = which;
ptr = reg->data;
hash = HASH(ptr);
reg->next = regions[hash];
regions[hash] = reg;
}
ast_mutex_unlock(&reglock);
if (!reg) {
fprintf(stderr, "Out of memory :(\n");
if (mmlog) {
fprintf(mmlog, "%ld - Out of memory\n", time(NULL));
fflush(mmlog);
}
}
return ptr;
}
static inline size_t __ast_sizeof_region(void *ptr)
{
int hash = HASH(ptr);
struct ast_region *reg;
size_t len = 0;
ast_mutex_lock(&reglock);
reg = regions[hash];
while(reg) {
if (reg->data == ptr) {
len = reg->len;
break;
}
reg = reg->next;
}
ast_mutex_unlock(&reglock);
return len;
}
static void __ast_free_region(void *ptr, const char *file, int lineno, const char *func)
{
int hash = HASH(ptr);
struct ast_region *reg, *prev = NULL;
ast_mutex_lock(&reglock);
reg = regions[hash];
while(reg) {
if (reg->data == ptr) {
if (prev)
prev->next = reg->next;
else
regions[hash] = reg->next;
break;
}
prev = reg;
reg = reg->next;
}
ast_mutex_unlock(&reglock);
if (reg) {
free(reg);
} else {
fprintf(stderr, "WARNING: Freeing unused memory at %p, in %s of %s, line %d\n",
ptr, func, file, lineno);
if (mmlog) {
fprintf(mmlog, "%ld - WARNING: Freeing unused memory at %p, in %s of %s, line %d\n", time(NULL),
ptr, func, file, lineno);
fflush(mmlog);
}
}
}
void *__ast_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
{
void *ptr;
ptr = __ast_alloc_region(size * nmemb, FUNC_CALLOC, file, lineno, func);
if (ptr)
memset(ptr, 0, size * nmemb);
return ptr;
}
void *__ast_malloc(size_t size, const char *file, int lineno, const char *func)
{
return __ast_alloc_region(size, FUNC_MALLOC, file, lineno, func);
}
void __ast_free(void *ptr, const char *file, int lineno, const char *func)
{
__ast_free_region(ptr, file, lineno, func);
}
void *__ast_realloc(void *ptr, size_t size, const char *file, int lineno, const char *func)
{
void *tmp;
size_t len=0;
if (ptr) {
len = __ast_sizeof_region(ptr);
if (!len) {
fprintf(stderr, "WARNING: Realloc of unalloced memory at %p, in %s of %s, line %d\n",
ptr, func, file, lineno);
if (mmlog) {
fprintf(mmlog, "%ld - WARNING: Realloc of unalloced memory at %p, in %s of %s, line %d\n",
time(NULL), ptr, func, file, lineno);
fflush(mmlog);
}
return NULL;
}
}
tmp = __ast_alloc_region(size, FUNC_REALLOC, file, lineno, func);
if (tmp) {
if (len > size)
len = size;
if (ptr) {
memcpy(tmp, ptr, len);
__ast_free_region(ptr, file, lineno, func);
}
}
return tmp;
}
char *__ast_strdup(const char *s, const char *file, int lineno, const char *func)
{
size_t len;
void *ptr;
if (!s)
return NULL;
len = strlen(s) + 1;
ptr = __ast_alloc_region(len, FUNC_STRDUP, file, lineno, func);
if (ptr)
strcpy(ptr, s);
return ptr;
}
char *__ast_strndup(const char *s, size_t n, const char *file, int lineno, const char *func)
{
size_t len;
void *ptr;
if (!s)
return NULL;
len = strlen(s) + 1;
if (len > n)
len = n;
ptr = __ast_alloc_region(len, FUNC_STRNDUP, file, lineno, func);
if (ptr)
strcpy(ptr, s);
return ptr;
}
int __ast_vasprintf(char **strp, const char *fmt, va_list ap, const char *file, int lineno, const char *func)
{
int n, size = strlen(fmt) + 1;
if ((*strp = __ast_alloc_region(size, FUNC_VASPRINTF, file, lineno, func)) == NULL)
return -1;
for (;;) {
n = vsnprintf(*strp, size, fmt, ap);
if (n > -1 && n < size)
return n;
if (n > -1) /* glibc 2.1 */
size = n+1;
else /* glibc 2.0 */
size *= 2;
if ((*strp = __ast_realloc(*strp, size, file, lineno, func)) == NULL)
return -1;
}
}
static int handle_show_memory(int fd, int argc, char *argv[])
{
char *fn = NULL;
int x;
struct ast_region *reg;
unsigned int len=0;
int count = 0;
if (argc >3)
fn = argv[3];
/* try to lock applications list ... */
ast_mutex_lock(&showmemorylock);
for (x=0;x<SOME_PRIME;x++) {
reg = regions[x];
while(reg) {
if (!fn || !strcasecmp(fn, reg->file)) {
ast_cli(fd, "%10d bytes allocated in %20s at line %5d of %s\n", reg->len, reg->func, reg->lineno, reg->file);
len += reg->len;
count++;
}
reg = reg->next;
}
}
ast_cli(fd, "%d bytes allocated %d units total\n", len, count);
ast_mutex_unlock(&showmemorylock);
return RESULT_SUCCESS;
}
struct file_summary {
char fn[80];
int len;
int count;
struct file_summary *next;
};
static int handle_show_memory_summary(int fd, int argc, char *argv[])
{
char *fn = NULL;
int x;
struct ast_region *reg;
unsigned int len=0;
int count = 0;
struct file_summary *list = NULL, *cur;
if (argc >3)
fn = argv[3];
/* try to lock applications list ... */
ast_mutex_lock(&reglock);
for (x=0;x<SOME_PRIME;x++) {
reg = regions[x];
while(reg) {
if (!fn || !strcasecmp(fn, reg->file)) {
cur = list;
while(cur) {
if ((!fn && !strcmp(cur->fn, reg->file)) || (fn && !strcmp(cur->fn, reg->func)))
break;
cur = cur->next;
}
if (!cur) {
cur = alloca(sizeof(struct file_summary));
memset(cur, 0, sizeof(struct file_summary));
strncpy(cur->fn, fn ? reg->func : reg->file, sizeof(cur->fn) - 1);
cur->next = list;
list = cur;
}
cur->len += reg->len;
cur->count++;
}
reg = reg->next;
}
}
ast_mutex_unlock(&reglock);
/* Dump the whole list */
while(list) {
cur = list;
len += list->len;
count += list->count;
if (fn)
ast_cli(fd, "%10d bytes in %5d allocations in function '%s' of '%s'\n", list->len, list->count, list->fn, fn);
else
ast_cli(fd, "%10d bytes in %5d allocations in file '%s'\n", list->len, list->count, list->fn);
list = list->next;
#if 0
free(cur);
#endif
}
ast_cli(fd, "%d bytes allocated %d units total\n", len, count);
return RESULT_SUCCESS;
}
static char show_memory_help[] =
"Usage: show memory allocations [<file>]\n"
" Dumps a list of all segments of allocated memory, optionally\n"
"limited to those from a specific file\n";
static char show_memory_summary_help[] =
"Usage: show memory summary [<file>]\n"
" Summarizes heap memory allocations by file, or optionally\n"
"by function, if a file is specified\n";
static struct ast_cli_entry show_memory_allocations_cli =
{ { "show", "memory", "allocations", NULL },
handle_show_memory, "Display outstanding memory allocations",
show_memory_help };
static struct ast_cli_entry show_memory_summary_cli =
{ { "show", "memory", "summary", NULL },
handle_show_memory_summary, "Summarize outstanding memory allocations",
show_memory_summary_help };
void __ast_mm_init(void)
{
ast_cli_register(&show_memory_allocations_cli);
ast_cli_register(&show_memory_summary_cli);
mmlog = fopen("/var/log/asterisk/mmlog", "a+");
if (option_verbose)
ast_verbose("Asterisk Malloc Debugger Started (see /var/log/asterisk/mmlog)\n");
if (mmlog) {
fprintf(mmlog, "%ld - New session\n", time(NULL));
fflush(mmlog);
}
}
#endif

View File

@@ -1,152 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Automatic channel service routines
*
* 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 <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <math.h> /* For PI */
#include <asterisk/pbx.h>
#include <asterisk/frame.h>
#include <asterisk/sched.h>
#include <asterisk/options.h>
#include <asterisk/channel.h>
#include <asterisk/channel_pvt.h>
#include <asterisk/logger.h>
#include <asterisk/file.h>
#include <asterisk/translate.h>
#include <asterisk/manager.h>
#include <asterisk/chanvars.h>
#include <asterisk/linkedlists.h>
#include <asterisk/indications.h>
#define MAX_AUTOMONS 256
static ast_mutex_t autolock = AST_MUTEX_INITIALIZER;
struct asent {
struct ast_channel *chan;
struct asent *next;
};
static struct asent *aslist = NULL;
static pthread_t asthread = (pthread_t) -1;
static void *autoservice_run(void *ign)
{
struct ast_channel *mons[MAX_AUTOMONS];
int x;
int ms;
struct ast_channel *chan;
struct asent *as;
struct ast_frame *f;
for(;;) {
x = 0;
ast_mutex_lock(&autolock);
as = aslist;
while(as) {
if (!as->chan->_softhangup) {
if (x < MAX_AUTOMONS)
mons[x++] = as->chan;
else
ast_log(LOG_WARNING, "Exceeded maximum number of automatic monitoring events. Fix autoservice.c\n");
}
as = as->next;
}
ast_mutex_unlock(&autolock);
/* if (!aslist)
break; */
ms = 500;
chan = ast_waitfor_n(mons, x, &ms);
if (chan) {
/* Read and ignore anything that occurs */
f = ast_read(chan);
if (f)
ast_frfree(f);
}
}
asthread = (pthread_t) -1;
return NULL;
}
int ast_autoservice_start(struct ast_channel *chan)
{
int res = -1;
struct asent *as;
int needstart;
ast_mutex_lock(&autolock);
needstart = (asthread == (pthread_t) -1) ? 1 : 0 /* aslist ? 0 : 1 */;
as = aslist;
while(as) {
if (as->chan == chan)
break;
as = as->next;
}
if (!as) {
as = malloc(sizeof(struct asent));
if (as) {
memset(as, 0, sizeof(struct asent));
as->chan = chan;
as->next = aslist;
aslist = as;
res = 0;
if (needstart) {
if (pthread_create(&asthread, NULL, autoservice_run, NULL)) {
ast_log(LOG_WARNING, "Unable to create autoservice thread :(\n");
free(aslist);
aslist = NULL;
res = -1;
} else
pthread_kill(asthread, SIGURG);
}
}
}
ast_mutex_unlock(&autolock);
return res;
}
int ast_autoservice_stop(struct ast_channel *chan)
{
int res = -1;
struct asent *as, *prev;
ast_mutex_lock(&autolock);
as = aslist;
prev = NULL;
while(as) {
if (as->chan == chan)
break;
prev = as;
as = as->next;
}
if (as) {
if (prev)
prev->next = as->next;
else
aslist = as->next;
free(as);
if (!chan->_softhangup)
res = 0;
}
if (asthread != (pthread_t) -1)
pthread_kill(asthread, SIGURG);
ast_mutex_unlock(&autolock);
/* Wait for it to un-block */
while(chan->blocking)
usleep(1000);
return res;
}

View File

@@ -21,11 +21,12 @@
#include <unistd.h>
#include <math.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 "sas.h"
#include "cas.h"
struct callerid_state {
fsk_data fskd;
@@ -42,76 +43,27 @@ struct callerid_state {
int len;
};
float cid_dr[4], cid_di[4];
float clidsb = 8000.0 / 1200.0;
float sasdr, sasdi;
float casdr1, casdi1, casdr2, casdi2;
static float dr[4], di[4];
static float clidsb = 8000.0 / 1200.0;
#define CALLERID_SPACE 2200.0 /* 2200 hz for "0" */
#define CALLERID_MARK 1200.0 /* 1200 hz for "1" */
#define SAS_FREQ 440.0
#define CAS_FREQ1 2130.0
#define CAS_FREQ2 2750.0
static inline void gen_tones(unsigned char *buf, int len, int codec, float ddr1, float ddi1, float ddr2, float ddi2, float *cr1, float *ci1, float *cr2, float *ci2)
{
int x;
float t;
for (x=0;x<len;x++) {
t = *cr1 * ddr1 - *ci1 * ddi1;
*ci1 = *cr1 * ddi1 + *ci1 * ddr1;
*cr1 = t;
t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
*cr1 *= t;
*ci1 *= t;
t = *cr2 * ddr2 - *ci2 * ddi2;
*ci2 = *cr2 * ddi2 + *ci2 * ddr2;
*cr2 = t;
t = 2.0 - (*cr2 * *cr2 + *ci2 * *ci2);
*cr2 *= t;
*ci2 *= t;
buf[x] = AST_LIN2X((*cr1 + *cr2) * 8192.0);
}
}
static inline void gen_tone(unsigned char *buf, int len, int codec, float ddr1, float ddi1, float *cr1, float *ci1)
{
int x;
float t;
for (x=0;x<len;x++) {
t = *cr1 * ddr1 - *ci1 * ddi1;
*ci1 = *cr1 * ddi1 + *ci1 * ddr1;
*cr1 = t;
t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
*cr1 *= t;
*ci1 *= t;
buf[x] = AST_LIN2X(*cr1 * 8192.0);
}
}
void callerid_init(void)
{
/* Initialize stuff for inverse FFT */
cid_dr[0] = cos(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
cid_di[0] = sin(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
cid_dr[1] = cos(CALLERID_MARK * 2.0 * M_PI / 8000.0);
cid_di[1] = sin(CALLERID_MARK * 2.0 * M_PI / 8000.0);
sasdr = cos(SAS_FREQ * 2.0 * M_PI / 8000.0);
sasdi = sin(SAS_FREQ * 2.0 * M_PI / 8000.0);
casdr1 = cos(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
casdi1 = sin(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
casdr2 = cos(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
casdi2 = sin(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
dr[0] = cos(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
di[0] = sin(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
dr[1] = cos(CALLERID_MARK * 2.0 * M_PI / 8000.0);
di[1] = sin(CALLERID_MARK * 2.0 * M_PI / 8000.0);
}
struct callerid_state *callerid_new(void)
{
struct callerid_state *cid;
cid = malloc(sizeof(struct callerid_state));
memset(cid, 0, sizeof(struct callerid_state));
if (cid) {
memset(cid, 0, sizeof(struct callerid_state));
cid->fskd.spb = 7; /* 1200 baud */
cid->fskd.hdlc = 0; /* Async */
cid->fskd.nbit = 8; /* 8 bits */
@@ -146,28 +98,34 @@ void callerid_get(struct callerid_state *cid, char **name, char **number, int *f
*number = cid->number;
}
int ast_gen_cas(unsigned char *outbuf, int sendsas, int len, int codec)
int ast_callerid_gen_cas(unsigned char *outbuf, int len)
{
int pos = 0;
int cnt;
int saslen=2400;
float cr1 = 1.0;
float ci1 = 0.0;
float cr2 = 1.0;
float ci2 = 0.0;
if (sendsas) {
if (len < saslen)
return -1;
gen_tone(outbuf, saslen, codec, sasdr, sasdi, &cr1, &ci1);
len -= saslen;
pos += saslen;
cr2 = cr1;
ci2 = ci1;
if (len < saslen)
return -1;
while(saslen) {
cnt = saslen;
if (cnt > sizeof(sas))
cnt = sizeof(sas);
memcpy(outbuf + pos, sas, cnt);
pos += cnt;
len -= cnt;
saslen -= cnt;
}
while(len) {
cnt = len;
if (cnt > sizeof(cas))
cnt = sizeof(cas);
memcpy(outbuf + pos, cas, cnt);
pos += cnt;
len -= cnt;
}
gen_tones(outbuf + pos, len, codec, casdr1, casdi1, casdr2, casdi2, &cr1, &ci1, &cr2, &ci2);
return 0;
}
int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int codec)
int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len)
{
int mylen = len;
int olen;
@@ -184,7 +142,7 @@ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int
memcpy(buf, cid->oldstuff, cid->oldlen);
mylen += cid->oldlen/2;
for (x=0;x<len;x++)
buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
buf[x+cid->oldlen/2] = ast_mulaw[ubuf[x]];
while(mylen >= 80) {
olen = mylen;
res = fsk_serie(&cid->fskd, buf, &mylen, &b);
@@ -253,7 +211,6 @@ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int
/* Date */
break;
case 2: /* Number */
case 3: /* Number (for Zebble) */
case 4: /* Number */
res = cid->rawdata[x];
if (res > 32) {
@@ -274,8 +231,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 22: /* Something French */
break;
default:
ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x-1]);
}
@@ -284,7 +239,7 @@ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int
}
} else {
/* SDMF */
strncpy(cid->number, cid->rawdata + 8, sizeof(cid->number)-1);
strncpy(cid->number, cid->rawdata + 8, sizeof(cid->number));
}
/* Update flags */
cid->flags = 0;
@@ -323,22 +278,22 @@ void callerid_free(struct callerid_state *cid)
free(cid);
}
static int callerid_genmsg(char *msg, int size, char *number, char *name, int flags)
static void callerid_genmsg(char *msg, int size, char *number, char *name, int flags)
{
time_t t;
struct tm tm;
struct tm *tm;
char *ptr;
int res;
int i,x;
/* Get the time */
time(&t);
localtime_r(&t,&tm);
tm = localtime(&t);
ptr = msg;
/* Format time and message header */
res = snprintf(ptr, size, "\001\010%02d%02d%02d%02d", tm.tm_mon + 1,
tm.tm_mday, tm.tm_hour, tm.tm_min);
res = snprintf(ptr, size, "\001\010%02d%02d%02d%02d", tm->tm_mon + 1,
tm->tm_mday, tm->tm_hour, tm->tm_min);
size -= res;
ptr += res;
if (!number || !strlen(number) || (flags & CID_UNKNOWN_NUMBER)) {
@@ -352,9 +307,9 @@ static int callerid_genmsg(char *msg, int size, char *number, char *name, int fl
size -= res;
ptr += res;
} else {
/* Send up to 16 digits of number MAX */
/* Send up to 10 digits of number MAX */
i = strlen(number);
if (i > 16) i = 16;
if (i > 10) i = 10;
res = snprintf(ptr, size, "\002%c", i);
size -= res;
ptr += res;
@@ -376,7 +331,7 @@ static int callerid_genmsg(char *msg, int size, char *number, char *name, int fl
size -= res;
ptr += res;
} else {
/* Send up to 16 digits of name MAX */
/* Send up to 10 digits of number MAX */
i = strlen(name);
if (i > 16) i = 16;
res = snprintf(ptr, size, "\007%c", i);
@@ -388,80 +343,70 @@ static int callerid_genmsg(char *msg, int size, char *number, char *name, int fl
ptr += i;
size -= i;
}
return (ptr - msg);
}
int vmwi_generate(unsigned char *buf, int active, int mdmf, int codec)
static inline float callerid_getcarrier(float *cr, float *ci, int bit)
{
unsigned char msg[256];
int len=0;
int sum;
int x;
int bytes = 0;
float cr = 1.0;
float ci = 0.0;
float scont = 0.0;
if (mdmf) {
/* MDMF Message waiting */
msg[len++] = 0x82;
/* Length is 3 */
msg[len++] = 3;
/* IE is "Message Waiting Parameter" */
msg[len++] = 0xb;
/* Length of IE is one */
msg[len++] = 1;
/* Active or not */
if (active)
msg[len++] = 0xff;
else
msg[len++] = 0x00;
} else {
/* SDMF Message waiting */
msg[len++] = 0x6;
/* Length is 3 */
msg[len++] = 3;
if (active) {
msg[len++] = 0x42;
msg[len++] = 0x42;
msg[len++] = 0x42;
} else {
msg[len++] = 0x6f;
msg[len++] = 0x6f;
msg[len++] = 0x6f;
}
}
sum = 0;
for (x=0;x<len;x++)
sum += msg[x];
sum = (256 - (sum & 255));
msg[len++] = sum;
/* Transmit 30 0x55's (looks like a square wave) for channel seizure */
for (x=0;x<30;x++)
PUT_CLID(0x55);
/* Send 170ms of callerid marks */
for (x=0;x<170;x++)
PUT_CLID_MARKMS;
for (x=0;x<len;x++) {
PUT_CLID(msg[x]);
}
/* Send 50 more ms of marks */
for (x=0;x<50;x++)
PUT_CLID_MARKMS;
return bytes;
}
/* Move along. There's nothing to see here... */
float t;
t = *cr * dr[bit] - *ci * di[bit];
*ci = *cr * di[bit] + *ci * dr[bit];
*cr = t;
t = 2.0 - (*cr * *cr + *ci * *ci);
*cr *= t;
*ci *= t;
return *cr;
}
int callerid_generate(unsigned char *buf, char *number, char *name, int flags, int callwaiting, int codec)
#define PUT_BYTE(a) do { \
*(buf++) = (a); \
bytes++; \
} while(0)
#define PUT_AUDIO_SAMPLE(y) do { \
int index = (short)(rint(8192.0 * (y))); \
*(buf++) = ast_lin2mu[index + 32768]; \
bytes++; \
} while(0)
#define PUT_CLID_MARKMS do { \
int x; \
for (x=0;x<8;x++) \
PUT_AUDIO_SAMPLE(callerid_getcarrier(&cr, &ci, 1)); \
} while(0)
#define PUT_CLID_BAUD(bit) do { \
while(scont < clidsb) { \
PUT_AUDIO_SAMPLE(callerid_getcarrier(&cr, &ci, bit)); \
scont += 1.0; \
} \
scont -= clidsb; \
} while(0)
#define PUT_CLID(byte) do { \
int z; \
unsigned char b = (byte); \
PUT_CLID_BAUD(0); /* Start bit */ \
for (z=0;z<8;z++) { \
PUT_CLID_BAUD(b & 1); \
b >>= 1; \
} \
PUT_CLID_BAUD(1); /* Stop bit */ \
} while(0);
int callerid_generate(unsigned char *buf, char *number, char *name, int flags, int callwaiting)
{
int bytes=0;
int x, sum;
int len;
/* Initial carriers (real/imaginary) */
float cr = 1.0;
float ci = 0.0;
float scont = 0.0;
unsigned char msg[256];
len = callerid_genmsg(msg, sizeof(msg), number, name, flags);
char msg[256];
callerid_genmsg(msg, sizeof(msg), number, name, flags);
if (!callwaiting) {
/* Wait a half a second */
for (x=0;x<4000;x++)
@@ -476,16 +421,15 @@ int callerid_generate(unsigned char *buf, char *number, char *name, int flags, i
/* Send 0x80 indicating MDMF format */
PUT_CLID(0x80);
/* Put length of whole message */
PUT_CLID(len);
PUT_CLID(strlen(msg));
sum = 0x80 + strlen(msg);
/* Put each character of message and update checksum */
for (x=0;x<len; x++) {
for (x=0;x<strlen(msg); x++) {
PUT_CLID(msg[x]);
sum += msg[x];
}
/* Send 2's compliment of sum */
PUT_CLID(256 - (sum & 255));
/* Send 50 more ms of marks */
for (x=0;x<50;x++)
PUT_CLID_MARKMS;
@@ -508,7 +452,7 @@ int ast_isphonenumber(char *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;
}
@@ -538,22 +482,19 @@ int ast_callerid_parse(char *instr, char **name, char **location)
instr[strlen(instr) - 1] = '\0';
/* And leading spaces */
while(**name && (**name < 33))
(*name)++;
name++;
return 0;
}
} else {
strncpy(tmp, instr, sizeof(tmp)-1);
strncpy(tmp, instr, sizeof(tmp));
ast_shrink_phone_number(tmp);
if (ast_isphonenumber(tmp)) {
/* Assume it's just a location */
*name = NULL;
*location = instr;
} else {
/* Assume it's just a name. Make sure it's not quoted though */
/* Assume it's just a name */
*name = instr;
while(*(*name) && ((*(*name) < 33) || (*(*name) == '\"'))) (*name)++;
ne = *name + strlen(*name) - 1;
while((ne > *name) && ((*ne < 33) || (*ne == '\"'))) { *ne = '\0'; ne--; }
*location = NULL;
}
return 0;
@@ -561,30 +502,30 @@ int ast_callerid_parse(char *instr, char **name, char **location)
return -1;
}
static int __ast_callerid_generate(unsigned char *buf, char *callerid, int callwaiting, int codec)
static int __ast_callerid_generate(unsigned char *buf, char *callerid, int callwaiting)
{
char tmp[256];
char *n, *l;
if (!callerid)
return callerid_generate(buf, NULL, NULL, 0, callwaiting, codec);
strncpy(tmp, callerid, sizeof(tmp)-1);
return callerid_generate(buf, NULL, NULL, 0, callwaiting);
strncpy(tmp, callerid, sizeof(tmp));
if (ast_callerid_parse(tmp, &n, &l)) {
ast_log(LOG_WARNING, "Unable to parse '%s' into CallerID name & number\n", callerid);
return callerid_generate(buf, NULL, NULL, 0, callwaiting, codec);
return callerid_generate(buf, NULL, NULL, 0, callwaiting);
}
if (l)
ast_shrink_phone_number(l);
if (!ast_isphonenumber(l))
return callerid_generate(buf, NULL, n, 0, callwaiting, codec);
return callerid_generate(buf, l, n, 0, callwaiting, codec);
return callerid_generate(buf, NULL, n, 0, callwaiting);
return callerid_generate(buf, l, n, 0, callwaiting);
}
int ast_callerid_generate(unsigned char *buf, char *callerid, int codec)
int ast_callerid_generate(unsigned char *buf, char *callerid)
{
return __ast_callerid_generate(buf, callerid, 0, codec);
return __ast_callerid_generate(buf, callerid, 0);
}
int ast_callerid_callwaiting_generate(unsigned char *buf, char *callerid, int codec)
int ast_callerid_callwaiting_generate(unsigned char *buf, char *callerid)
{
return __ast_callerid_generate(buf, callerid, 1, codec);
return __ast_callerid_generate(buf, callerid, 1);
}

58
cas.h Normal file
View File

@@ -0,0 +1,58 @@
/* cas.h: Generated from frequencies 2130 and 2750
by gensound. 800 samples */
static unsigned char cas[800] = {
255, 177, 60, 69, 189, 105, 95, 95, 90, 188, 78, 56, 180, 207, 48,
196, 191, 63, 117, 226, 224, 207, 60, 229, 180, 56, 66, 176, 80, 60,
194, 226, 103, 101, 74, 189, 223, 50, 190, 187, 50, 241, 186, 72, 90,
237, 238, 198, 63, 76, 177, 72, 54, 180, 215, 57, 207, 214, 120, 251,
66, 196, 193, 49, 219, 178, 57, 73, 185, 91, 83, 124, 103, 191, 75,
60, 179, 223, 48, 190, 191, 59, 241, 211, 244, 220, 63, 216, 184, 54,
74, 175, 72, 59, 189, 230, 84, 113, 83, 191, 255, 53, 187, 190, 48,
217, 185, 64, 89, 214, 243, 205, 64, 87, 179, 65, 57, 178, 233, 55,
199, 208, 90, 122, 74, 196, 201, 50, 206, 180, 53, 78, 183, 79, 77,
222, 119, 199, 74, 64, 179, 111, 49, 186, 194, 55, 222, 203, 101, 234,
69, 210, 187, 54, 84, 175, 64, 60, 185, 246, 75, 236, 96, 196, 100,
56, 185, 196, 47, 204, 184, 60, 91, 203, 117, 218, 69, 104, 182, 62,
60, 176, 104, 54, 191, 207, 77, 252, 84, 199, 210, 52, 200, 183, 51,
89, 180, 72, 74, 207, 255, 207, 74, 72, 180, 89, 51, 183, 200, 52,
210, 199, 84, 252, 77, 207, 191, 54, 104, 176, 60, 62, 182, 104, 69,
218, 117, 203, 91, 60, 184, 204, 47, 196, 185, 56, 100, 196, 96, 236,
75, 246, 185, 60, 64, 175, 84, 54, 187, 210, 69, 234, 101, 203, 222,
55, 194, 186, 49, 111, 179, 64, 74, 199, 119, 222, 77, 79, 183, 78,
53, 180, 206, 50, 201, 196, 74, 122, 90, 208, 199, 55, 233, 178, 57,
65, 179, 87, 64, 205, 243, 214, 89, 64, 185, 217, 48, 190, 187, 53,
255, 191, 83, 113, 84, 230, 189, 59, 72, 175, 74, 54, 184, 216, 63,
220, 244, 211, 241, 59, 191, 190, 48, 223, 179, 60, 75, 191, 103, 124,
83, 91, 185, 73, 57, 178, 219, 49, 193, 196, 66, 251, 120, 214, 207,
57, 215, 180, 54, 72, 177, 76, 63, 198, 238, 237, 90, 72, 186, 241,
50, 187, 190, 50, 223, 189, 74, 101, 103, 226, 194, 60, 80, 176, 66,
56, 180, 229, 60, 207, 224, 226, 117, 63, 191, 196, 48, 207, 180, 56,
78, 188, 90, 95, 95, 105, 189, 69, 60, 177, 255, 49, 188, 197, 61,
233, 223, 223, 218, 60, 206, 184, 52, 79, 176, 68, 63, 191, 245, 98,
96, 79, 188, 101, 52, 184, 194, 48, 208, 188, 66, 98, 231, 229, 202,
61, 95, 178, 62, 59, 178, 113, 58, 200, 218, 109, 110, 70, 191, 204,
49, 200, 182, 52, 87, 185, 79, 86, 248, 123, 194, 68, 65, 177, 91,
50, 185, 201, 57, 219, 211, 252, 231, 63, 203, 188, 51, 95, 176, 62,
63, 187, 113, 83, 116, 92, 191, 88, 56, 182, 202, 47, 200, 187, 61,
102, 212, 241, 211, 63, 255, 181, 59, 62, 176, 89, 57, 192, 217, 86,
115, 77, 192, 215, 51, 193, 185, 50, 105, 183, 71, 80, 218, 250, 202,
68, 73, 178, 78, 52, 181, 206, 55, 207, 205, 94, 247, 71, 202, 192,
51, 239, 177, 58, 66, 183, 94, 75, 229, 106, 197, 82, 59, 182, 212,
47, 192, 188, 57, 118, 203, 108, 224, 68, 228, 184, 57, 68, 175, 76,
56, 188, 219, 75, 245, 90, 197, 232, 54, 190, 188, 48, 232, 182, 63,
79, 205, 124, 212, 71, 82, 180, 72, 55, 179, 217, 52, 200, 202, 79,
255, 79, 202, 200, 52, 217, 179, 55, 72, 180, 82, 71, 212, 124, 205,
79, 63, 182, 232, 48, 188, 190, 54, 232, 197, 90, 245, 75, 219, 188,
56, 76, 175, 68, 57, 184, 228, 68, 224, 108, 203, 118, 57, 188, 192,
47, 212, 182, 59, 82, 197, 106, 229, 75, 94, 183, 66, 58, 177, 239,
51, 192, 202, 71, 247, 94, 205, 207, 55, 206, 181, 52, 78, 178, 73,
68, 202, 250, 218, 80, 71, 183, 105, 50, 185, 193, 51, 215, 192, 77,
115, 86, 217, 192, 57, 89, 176, 62, 59, 181, 255, 63, 211, 241, 212,
102, 61, 187, 200, 47, 202, 182, 56, 88, 191, 92, 116, 83, 113, 187,
63, 62, 176, 95, 51, 188, 203, 63, 231, 252, 211, 219, 57, 201, 185,
50, 91, 177, 65, 68, 194, 123, 248, 86, 79, 185, 87, 52, 182, 200,
49, 204, 191, 70, 110, 109, 218, 200, 58, 113, 178, 59, 62, 178, 95,
61, 202, 229, 231, 98, 66, 188, 208, 48, 194, 184, 52, 101, 188, 79,
96, 98, 245, 191, 63, 68, 176, 79, 52, 184, 206, 60, 218, 223, 223,
233, 61, 197, 188, 49,
};

459
cdr.c
View File

@@ -1,459 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Call Detail Record API
*
* 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.
*
* Includes code and algorithms from the Zapata library.
*
*/
#include <asterisk/lock.h>
#include <asterisk/channel.h>
#include <asterisk/cdr.h>
#include <asterisk/logger.h>
#include <asterisk/callerid.h>
#include <asterisk/causes.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] = "";
static ast_mutex_t cdrlock = AST_MUTEX_INITIALIZER;
static struct ast_cdr_beitem {
char name[20];
char desc[80];
ast_cdrbe be;
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
* or a WARNING shall be logged, so that we can best keep track of any escape condition where the CDR
* isn't properly generated and posted.
*/
int ast_cdr_register(char *name, char *desc, ast_cdrbe be)
{
struct ast_cdr_beitem *i;
if (!name)
return -1;
if (!be) {
ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name);
return -1;
}
ast_mutex_lock(&cdrlock);
i = bes;
while(i) {
if (!strcasecmp(name, i->name))
break;
i = i->next;
}
ast_mutex_unlock(&cdrlock);
if (i) {
ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name);
return -1;
}
i = malloc(sizeof(struct ast_cdr_beitem));
if (!i)
return -1;
memset(i, 0, sizeof(struct ast_cdr_beitem));
strncpy(i->name, name, sizeof(i->name) - 1);
strncpy(i->desc, desc, sizeof(i->desc) - 1);
i->be = be;
ast_mutex_lock(&cdrlock);
i->next = bes;
bes = i;
ast_mutex_unlock(&cdrlock);
return 0;
}
void ast_cdr_unregister(char *name)
{
struct ast_cdr_beitem *i, *prev = NULL;
ast_mutex_lock(&cdrlock);
i = bes;
while(i) {
if (!strcasecmp(name, i->name)) {
if (prev)
prev->next = i->next;
else
bes = i->next;
break;
}
i = i->next;
}
ast_mutex_unlock(&cdrlock);
if (i)
free(i);
}
void ast_cdr_free(struct ast_cdr *cdr)
{
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);
}
}
struct ast_cdr *ast_cdr_alloc(void)
{
struct ast_cdr *cdr;
cdr = malloc(sizeof(struct ast_cdr));
if (cdr) {
memset(cdr, 0, sizeof(struct ast_cdr));
}
return cdr;
}
void ast_cdr_start(struct ast_cdr *cdr)
{
char *chan;
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;
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);
}
}
}
void ast_cdr_busy(struct ast_cdr *cdr)
{
char *chan;
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;
if (cdr) {
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
if (cdr->posted)
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
cdr->disposition = AST_CDR_FAILED;
}
}
int ast_cdr_disposition(struct ast_cdr *cdr, int cause)
{
int res = 0;
if (cdr) {
switch(cause) {
case AST_CAUSE_BUSY:
ast_cdr_busy(cdr);
break;
case AST_CAUSE_FAILURE:
ast_cdr_failed(cdr);
break;
case AST_CAUSE_NORMAL:
break;
case AST_CAUSE_NOTDEFINED:
res = -1;
break;
default:
res = -1;
ast_log(LOG_WARNING, "We don't handle that cause yet\n");
}
}
return res;
}
void ast_cdr_setdestchan(struct ast_cdr *cdr, char *chann)
{
char *chan;
if (cdr) {
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
if (cdr->posted)
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
strncpy(cdr->dstchannel, chann, sizeof(cdr->dstchannel) - 1);
}
}
void ast_cdr_setapp(struct ast_cdr *cdr, char *app, char *data)
{
char *chan;
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);
}
}
int ast_cdr_setcid(struct ast_cdr *cdr, struct ast_channel *c)
{
char tmp[AST_MAX_EXTENSION] = "";
char *num, *name;
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);
}
}
return 0;
}
int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *c)
{
char *chan;
char *num, *name;
char tmp[AST_MAX_EXTENSION] = "";
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);
}
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;
}
void ast_cdr_end(struct ast_cdr *cdr)
{
char *chan;
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);
}
}
char *ast_cdr_disp2str(int disposition)
{
switch (disposition) {
case AST_CDR_NOANSWER:
return "NO ANSWER";
case AST_CDR_FAILED:
return "FAILED";
case AST_CDR_BUSY:
return "BUSY";
case AST_CDR_ANSWERED:
return "ANSWERED";
default:
return "UNKNOWN";
}
}
char *ast_cdr_flags2str(int flag)
{
switch(flag) {
case AST_CDR_OMIT:
return "OMIT";
case AST_CDR_BILLING:
return "BILLING";
case AST_CDR_DOCUMENTATION:
return "DOCUMENTATION";
}
return "Unknown";
}
int ast_cdr_setaccount(struct ast_channel *chan, char *account)
{
struct ast_cdr *cdr = chan->cdr;
strncpy(chan->accountcode, account, sizeof(chan->accountcode) - 1);
if (cdr)
strncpy(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode) - 1);
return 0;
}
int ast_cdr_setuserfield(struct ast_channel *chan, char *userfield)
{
struct ast_cdr *cdr = chan->cdr;
if (cdr)
strncpy(cdr->userfield, userfield, sizeof(cdr->userfield) - 1);
return 0;
}
int ast_cdr_appenduserfield(struct ast_channel *chan, char *userfield)
{
struct ast_cdr *cdr = chan->cdr;
if (cdr)
{
int len = strlen(cdr->userfield);
strncpy(cdr->userfield+len, userfield, sizeof(cdr->userfield) - len - 1);
}
return 0;
}
int ast_cdr_update(struct ast_channel *c)
{
struct ast_cdr *cdr = c->cdr;
char *name, *num;
char tmp[AST_MAX_EXTENSION] = "";
/* Grab source from ANI or normal Caller*ID */
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);
}
/* 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;
}
int ast_cdr_amaflags2int(char *flag)
{
if (!strcasecmp(flag, "default"))
return 0;
if (!strcasecmp(flag, "omit"))
return AST_CDR_OMIT;
if (!strcasecmp(flag, "billing"))
return AST_CDR_BILLING;
if (!strcasecmp(flag, "documentation"))
return AST_CDR_DOCUMENTATION;
return -1;
}
void ast_cdr_post(struct ast_cdr *cdr)
{
char *chan;
struct ast_cdr_beitem *i;
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);
if (!cdr->start.tv_sec && !cdr->start.tv_usec)
ast_log(LOG_WARNING, "CDR on channel '%s' lacks start\n", chan);
cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec + (cdr->end.tv_usec - cdr->start.tv_usec) / 1000000;
if (cdr->answer.tv_sec || cdr->answer.tv_usec) {
cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec + (cdr->end.tv_usec - cdr->answer.tv_usec) / 1000000;
} else
cdr->billsec = 0;
cdr->posted = 1;
ast_mutex_lock(&cdrlock);
i = bes;
while(i) {
i->be(cdr);
i = i->next;
}
ast_mutex_unlock(&cdrlock);
}
}
void ast_cdr_reset(struct ast_cdr *cdr, int post)
{
if (cdr) {
/* 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;
}
}

View File

@@ -1,67 +0,0 @@
#
# Asterisk -- A telephony toolkit for Linux.
#
# Makefile for CDR backends (dynamically loaded)
#
# 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
#
#ADD cdr_pgsql.so to MODS= to include PostgreSQL support: REQUIRES PostgreSQL libs
MODS=cdr_csv.so
CFLAGS+=-fPIC
#
# 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)
#
# PGSQL stuff... Autoconf anyone??
#
MODS+=$(shell if [ -d /usr/local/pgsql/include ] || [ -d /usr/include/pgsql ] || [ -d /usr/local/include/pgsql ] || [ -d /opt/pgsql/include ] || [ -f /usr/include/libpq-fe.h ] ; then echo "cdr_pgsql.so"; fi)
CFLAGS+=$(shell if [ -d /usr/local/pgsql/include ]; then echo "-I/usr/local/pgsql/include"; fi)
CFLAGS+=$(shell if [ -d /usr/include/pgsql ]; then echo "-I/usr/include/pgsql"; fi)
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)
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)
MLFLAGS+=$(shell if [ -d /usr/local/lib/pgsql ]; then echo "-L/usr/local/lib/pgsql"; fi)
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)
all: depend $(MODS)
install: all
for x in $(MODS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
clean:
rm -f *.so *.o .depend
%.so : %.o
$(CC) $(SOLINK) -o $@ $<
ifneq ($(wildcard .depend),)
include .depend
endif
cdr_odbc.so: cdr_odbc.o
$(CC) $(SOLINK) -o $@ $< -lodbc $(MLFLAGS)
cdr_pgsql.so: cdr_pgsql.o
$(CC) $(SOLINK) -o $@ $< -lpq -lz $(MLFLAGS)
depend: .depend
.depend:
../mkdep $(CFLAGS) `ls *.c`

View File

@@ -1,274 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Comma Separated Value CDR records.
*
* 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.
*
* Includes code and algorithms from the Zapata library.
*
*/
#include <sys/types.h>
#include <asterisk/channel.h>
#include <asterisk/cdr.h>
#include <asterisk/module.h>
#include <asterisk/logger.h>
#include "../asterisk.h"
#include "../astconf.h"
#define CSV_LOG_DIR "/cdr-csv"
#define CSV_MASTER "/Master.csv"
#define DATE_FORMAT "%Y-%m-%d %T"
/* #define CSV_LOGUNIQUEID 1 */
/* #define CSV_LOGUSERFIELD 1 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
/* The values are as follows:
"accountcode", // accountcode is the account name of detail records, Master.csv contains all records
// Detail records are configured on a channel basis, IAX and SIP are determined by user
// Zap is determined by channel in zaptel.conf
"source",
"destination",
"destination context",
"callerid",
"channel",
"destination channel", (if applicable)
"last application", // Last application run on the channel
"last app argument", // argument to the last channel
"start time",
"answer time",
"end time",
duration, // Duration is the whole length that the entire call lasted. ie. call rx'd to hangup
// "end time" minus "start time"
billable seconds, // the duration that a call was up after other end answered which will be <= to duration
// "end time" minus "answer time"
"disposition", // ANSWERED, NO ANSWER, BUSY
"amaflags", // DOCUMENTATION, BILL, IGNORE etc, specified on a per channel basis like accountcode.
"uniqueid", // unique call identifier
"userfield" // user field set via SetCDRUserField
*/
static char *desc = "Comma Separated Values CDR Backend";
static char *name = "csv";
static FILE *mf = NULL;
static int append_string(char *buf, char *s, int len)
{
int pos = strlen(buf);
int spos = 0;
int error = 0;
if (pos >= len - 4)
return -1;
buf[pos++] = '\"';
error = -1;
while(pos < len - 3) {
if (!s[spos]) {
error = 0;
break;
}
if (s[spos] == '\"')
buf[pos++] = '\"';
buf[pos++] = s[spos];
spos++;
}
buf[pos++] = '\"';
buf[pos++] = ',';
buf[pos++] = '\0';
return error;
}
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) > len - 3)
return -1;
strncat(buf, tmp, len);
pos = strlen(buf);
buf[pos++] = ',';
buf[pos++] = '\0';
return 0;
}
static int append_date(char *buf, struct timeval tv, int len)
{
char tmp[80];
struct tm tm;
time_t t;
t = tv.tv_sec;
if (strlen(buf) > len - 3)
return -1;
if (!tv.tv_sec && !tv.tv_usec) {
strncat(buf, ",", len);
return 0;
}
localtime_r(&t,&tm);
strftime(tmp, sizeof(tmp), DATE_FORMAT, &tm);
return append_string(buf, tmp, len);
}
static int build_csv_record(char *buf, int len, struct ast_cdr *cdr)
{
buf[0] = '\0';
/* Account code */
append_string(buf, cdr->accountcode, len);
/* Source */
append_string(buf, cdr->src, len);
/* Destination */
append_string(buf, cdr->dst, len);
/* Destination context */
append_string(buf, cdr->dcontext, len);
/* Caller*ID */
append_string(buf, cdr->clid, len);
/* Channel */
append_string(buf, cdr->channel, len);
/* Destination Channel */
append_string(buf, cdr->dstchannel, len);
/* Last Application */
append_string(buf, cdr->lastapp, len);
/* Last Data */
append_string(buf, cdr->lastdata, len);
/* Start Time */
append_date(buf, cdr->start, len);
/* Answer Time */
append_date(buf, cdr->answer, len);
/* End Time */
append_date(buf, cdr->end, len);
/* Duration */
append_int(buf, cdr->duration, len);
/* Billable seconds */
append_int(buf, cdr->billsec, len);
/* Disposition */
append_string(buf, ast_cdr_disp2str(cdr->disposition), len);
/* AMA Flags */
append_string(buf, ast_cdr_flags2str(cdr->amaflags), len);
#ifdef CSV_LOGUNIQUEID
/* Unique ID */
append_string(buf, cdr->uniqueid, len);
#endif
#ifdef CSV_LOGUSERFIELD
/* append the user field */
append_string(buf, cdr->userfield,len);
#endif
/* If we hit the end of our buffer, log an error */
if (strlen(buf) < len - 5) {
/* Trim off trailing comma */
buf[strlen(buf) - 1] = '\0';
strncat(buf, "\n", len);
return 0;
}
return -1;
}
static int writefile(char *s, char *acc)
{
char tmp[256];
FILE *f;
if (strchr(acc, '/') || (acc[0] == '.')) {
ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n", acc);
return -1;
}
snprintf(tmp, sizeof(tmp), "%s/%s/%s.csv", (char *)ast_config_AST_LOG_DIR,CSV_LOG_DIR, acc);
f = fopen(tmp, "a");
if (!f)
return -1;
fputs(s, f);
fclose(f);
return 0;
}
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((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", 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\n", csvmaster);
}
if (mf) {
fputs(buf, mf);
fflush(mf); /* be particularly anal here */
fclose(mf);
mf = NULL;
}
if (strlen(cdr->accountcode)) {
if (writefile(buf, cdr->accountcode))
ast_log(LOG_WARNING, "Unable to write CSV record to account file '%s'\n", cdr->accountcode);
}
}
return 0;
}
char *description(void)
{
return desc;
}
int unload_module(void)
{
if (mf)
fclose(mf);
ast_cdr_unregister(name);
return 0;
}
int load_module(void)
{
int res;
res = ast_cdr_register(name, desc, csv_log);
if (res) {
ast_log(LOG_ERROR, "Unable to register CSV CDR handling\n");
if (mf)
fclose(mf);
}
return res;
}
int reload(void)
{
return 0;
}
int usecount(void)
{
return 0;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,492 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* ODBC CDR Backend
*
* Brian K. West <brian@bkw.org>
*
* This program is free software, distributed under the terms of
* the GNU General Public License.
*
* Copyright (c) 2003 Digium, Inc.
*
*/
#include <sys/types.h>
#include <asterisk/config.h>
#include <asterisk/options.h>
#include <asterisk/channel.h>
#include <asterisk/cdr.h>
#include <asterisk/module.h>
#include <asterisk/logger.h>
#include "../asterisk.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sql.h>
#include <sqlext.h>
#include <sqltypes.h>
#define DATE_FORMAT "%Y-%m-%d %T"
static char *desc = "ODBC CDR Backend";
static char *name = "ODBC";
static char *config = "cdr_odbc.conf";
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;
static ast_mutex_t odbc_lock = AST_MUTEX_INITIALIZER;
static int odbc_do_query(void);
static int odbc_init(void);
static SQLHENV ODBC_env = SQL_NULL_HANDLE; /* global ODBC Environment */
static SQLHDBC ODBC_con; /* global ODBC Connection Handle */
static SQLHSTMT ODBC_stmt; /* global ODBC Statement Handle */
static int odbc_log(struct ast_cdr *cdr)
{
long int ODBC_err;
short int ODBC_mlen;
int ODBC_res;
char ODBC_msg[200], ODBC_stat[10];
char sqlcmd[2048], timestr[128];
int res = 0;
struct tm tm;
struct timeval tv;
time_t t;
gettimeofday(&tv,NULL);
t = tv.tv_sec;
localtime_r(&t,&tm);
ast_mutex_lock(&odbc_lock);
strftime(timestr,128,DATE_FORMAT,&tm);
memset(sqlcmd,0,2048);
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
{
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)
{
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 > 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);
connected = 0;
ast_mutex_unlock(&odbc_lock);
return 0;
}
/* We really should only have to do this once. But for some
strange reason if I don't it blows holes in memory like
like a shotgun. So we just do this so its safe. */
ODBC_res = SQLPrepare(ODBC_stmt, sqlcmd, SQL_NTS);
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);
connected = 0;
ast_mutex_unlock(&odbc_lock);
return 0;
}
SQLBindParameter(ODBC_stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, &timestr, 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 != 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)
{
res = odbc_do_query();
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 > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Reconnecting to dsn %s\n", dsn);
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 > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Trying Query again!\n");
res = odbc_do_query();
if(res < 0)
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query FAILED Call not logged!\n");
}
}
}
}
else
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query FAILED Call not logged!\n");
}
ast_mutex_unlock(&odbc_lock);
return 0;
}
char *description(void)
{
return desc;
}
static int odbc_unload_module(void)
{
ast_mutex_lock(&odbc_lock);
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);
SQLFreeHandle(SQL_HANDLE_DBC, ODBC_con);
SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
connected = 0;
}
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 > 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 > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free password\n");
free(password);
password = NULL;
password_alloc = 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;
}
static int odbc_load_module(void)
{
int res = 0;
struct ast_config *cfg;
struct ast_variable *var;
char *tmp;
ast_mutex_lock(&odbc_lock);
cfg = ast_load(config);
if (!cfg)
{
ast_log(LOG_WARNING, "cdr_odbc: Unable to load config for ODBC CDR's: %s\n", config);
goto out;
}
var = ast_variable_browse(cfg, "global");
if (!var) {
/* nothing configured */
goto out;
}
tmp = ast_variable_retrieve(cfg,"global","dsn");
if (tmp)
{
dsn = malloc(strlen(tmp) + 1);
if (dsn != NULL)
{
dsn_alloc = 1;
strcpy(dsn,tmp);
}
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)
{
username = malloc(strlen(tmp) + 1);
if (username != NULL)
{
username_alloc = 1;
strcpy(username,tmp);
}
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)
{
password = malloc(strlen(tmp) + 1);
if (password != NULL)
{
password_alloc = 1;
strcpy(password,tmp);
}
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 = 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");
loguniqueid_alloc = 1;
loguniqueid = NULL;
}
}
else
{
ast_log(LOG_WARNING,"cdr_odbc: Not logging uniqueid\n");
loguniqueid = NULL;
}
ast_destroy(cfg);
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)
{
ast_log(LOG_ERROR, "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)
{
ast_log(LOG_ERROR, "cdr_odbc: Unable to register ODBC CDR handling\n");
}
out:
ast_mutex_unlock(&odbc_lock);
return res;
}
static int odbc_do_query(void)
{
long int ODBC_err;
int ODBC_res;
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 > 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 > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query Successful!\n");
connected = 1;
}
return 0;
}
static int odbc_init(void)
{
long int ODBC_err;
short int ODBC_mlen;
int ODBC_res;
char ODBC_msg[200], ODBC_stat[10];
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 > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error AllocHandle\n");
connected = 0;
return -1;
}
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 > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error SetEnv\n");
SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
connected = 0;
return -1;
}
ODBC_res = SQLAllocHandle(SQL_HANDLE_DBC, ODBC_env, &ODBC_con);
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 > 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 > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Connected to %s\n", dsn);
connected = 1;
}
return 0;
}
int load_module(void)
{
return odbc_load_module();
}
int unload_module(void)
{
return odbc_unload_module();
}
int reload(void)
{
odbc_unload_module();
return odbc_load_module();
}
int usecount(void)
{
return connected;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,333 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* PostgreSQL CDR logger
*
* Matthew D. Hardeman <mhardemn@papersoft.com>
* Adapted from the MySQL CDR logger originally by James Sharp
*
* Modified September 2003
* Matthew D. Hardeman <mhardemn@papersoft.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License.
*
*/
#include <sys/types.h>
#include <asterisk/config.h>
#include <asterisk/options.h>
#include <asterisk/channel.h>
#include <asterisk/cdr.h>
#include <asterisk/module.h>
#include <asterisk/logger.h>
#include "../asterisk.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <libpq-fe.h>
#define DATE_FORMAT "%Y-%m-%d %T"
static char *desc = "PostgreSQL CDR Backend";
static char *name = "pgsql";
static char *config = "cdr_pgsql.conf";
static char *pghostname = NULL, *pgdbname = NULL, *pgdbuser = NULL, *pgpassword = NULL, *pgdbsock = NULL, *pgdbport = NULL;
static int hostname_alloc = 0, dbname_alloc = 0, dbuser_alloc = 0, password_alloc = 0, dbsock_alloc = 0, dbport_alloc = 0;
static int connected = 0;
static ast_mutex_t pgsql_lock = AST_MUTEX_INITIALIZER;
PGconn *conn;
PGresult *result;
static int pgsql_log(struct ast_cdr *cdr)
{
struct tm tm;
struct timeval tv;
char sqlcmd[2048], timestr[128];
time_t t;
char *pgerror;
ast_mutex_lock(&pgsql_lock);
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);
if (PQstatus(conn) != CONNECTION_BAD) {
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: Reason: %s\n", pgerror);
}
}
if (connected) {
char *clid=NULL, *dcontext=NULL, *channel=NULL, *dstchannel=NULL, *lastapp=NULL, *lastdata=NULL;
char *uniqueid=NULL, *userfield=NULL;
/* Maximum space needed would be if all characters needed to be escaped, plus a trailing NULL */
if ((clid = alloca(strlen(cdr->clid) * 2 + 1)) != NULL)
PQescapeString(clid, cdr->clid, strlen(cdr->clid));
if ((dcontext = alloca(strlen(cdr->dcontext) * 2 + 1)) != NULL)
PQescapeString(dcontext, cdr->dcontext, strlen(cdr->dcontext));
if ((channel = alloca(strlen(cdr->channel) * 2 + 1)) != NULL)
PQescapeString(channel, cdr->channel, strlen(cdr->channel));
if ((dstchannel = alloca(strlen(cdr->dstchannel) * 2 + 1)) != NULL)
PQescapeString(dstchannel, cdr->dstchannel, strlen(cdr->dstchannel));
if ((lastapp = alloca(strlen(cdr->lastapp) * 2 + 1)) != NULL)
PQescapeString(lastapp, cdr->lastapp, strlen(cdr->lastapp));
if ((lastdata = alloca(strlen(cdr->lastdata) * 2 + 1)) != NULL)
PQescapeString(lastdata, cdr->lastdata, strlen(cdr->lastdata));
if ((uniqueid = alloca(strlen(cdr->uniqueid) * 2 + 1)) != NULL)
PQescapeString(uniqueid, cdr->uniqueid, strlen(cdr->uniqueid));
if ((userfield = alloca(strlen(cdr->userfield) * 2 + 1)) != NULL)
PQescapeString(userfield, cdr->userfield, strlen(cdr->userfield));
/* Check for all alloca failures above at once */
if ((!clid) || (!dcontext) || (!channel) || (!dstchannel) || (!lastapp) || (!lastdata) || (!uniqueid) || (!userfield)) {
ast_log(LOG_ERROR, "cdr_pgsql: Out of memory error (insert fails)\n");
ast_mutex_unlock(&pgsql_lock);
return -1;
}
ast_log(LOG_DEBUG,"cdr_pgsql: inserting a CDR record.\n");
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... */
/* If we're connected, and connection is working, good. */
/* Otherwise, attempt reconnect. If it fails... sorry... */
if (PQstatus(conn) == CONNECTION_OK) {
connected = 1;
} else {
ast_log(LOG_ERROR, "cdr_pgsql: Connection was lost... attempting to reconnect.\n");
PQreset(conn);
if (PQstatus(conn) == CONNECTION_OK) {
ast_log(LOG_ERROR, "cdr_pgsql: Connection reestablished.\n");
connected = 1;
} else {
pgerror = PQerrorMessage(conn);
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;
return -1;
}
}
result = PQexec(conn, sqlcmd);
if ( PQresultStatus(result) != PGRES_COMMAND_OK) {
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_mutex_unlock(&pgsql_lock);
return -1;
}
}
ast_mutex_unlock(&pgsql_lock);
return 0;
}
char *description(void)
{
return desc;
}
static int my_unload_module(void)
{
PQfinish(conn);
connected = 0;
if (pghostname && hostname_alloc) {
free(pghostname);
pghostname = NULL;
hostname_alloc = 0;
}
if (pgdbname && dbname_alloc) {
free(pgdbname);
pgdbname = NULL;
dbname_alloc = 0;
}
if (pgdbuser && dbuser_alloc) {
free(pgdbuser);
pgdbuser = NULL;
dbuser_alloc = 0;
}
if (pgdbsock && dbsock_alloc) {
free(pgdbsock);
pgdbsock = NULL;
dbsock_alloc = 0;
}
if (pgpassword && password_alloc) {
free(pgpassword);
pgpassword = NULL;
password_alloc = 0;
}
if (pgdbport && dbport_alloc) {
free(pgdbport);
pgdbport = NULL;
dbport_alloc = 0;
}
ast_cdr_unregister(name);
return 0;
}
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 */
return 0;
}
tmp = ast_variable_retrieve(cfg,"global","hostname");
if (tmp) {
pghostname = malloc(strlen(tmp) + 1);
if (pghostname != NULL) {
hostname_alloc = 1;
strcpy(pghostname,tmp);
} else {
ast_log(LOG_ERROR,"Out of memory error.\n");
return -1;
}
} else {
ast_log(LOG_WARNING,"PostgreSQL server hostname not specified. Assuming localhost\n");
pghostname = "localhost";
}
tmp = ast_variable_retrieve(cfg,"global","dbname");
if (tmp) {
pgdbname = malloc(strlen(tmp) + 1);
if (pgdbname != NULL) {
dbname_alloc = 1;
strcpy(pgdbname,tmp);
} else {
ast_log(LOG_ERROR,"Out of memory error.\n");
return -1;
}
} else {
ast_log(LOG_WARNING,"PostgreSQL database not specified. Assuming asterisk\n");
pgdbname = "asteriskcdrdb";
}
tmp = ast_variable_retrieve(cfg,"global","user");
if (tmp) {
pgdbuser = malloc(strlen(tmp) + 1);
if (pgdbuser != NULL) {
dbuser_alloc = 1;
strcpy(pgdbuser,tmp);
} else {
ast_log(LOG_ERROR,"Out of memory error.\n");
return -1;
}
} else {
ast_log(LOG_WARNING,"PostgreSQL database user not specified. Assuming root\n");
pgdbuser = "root";
}
tmp = ast_variable_retrieve(cfg,"global","password");
if (tmp) {
pgpassword = malloc(strlen(tmp) + 1);
if (pgpassword != NULL) {
password_alloc = 1;
strcpy(pgpassword,tmp);
} else {
ast_log(LOG_ERROR,"Out of memory error.\n");
return -1;
}
} else {
ast_log(LOG_WARNING,"PostgreSQL database password not specified. Assuming blank\n");
pgpassword = "";
}
tmp = ast_variable_retrieve(cfg,"global","port");
if (tmp) {
pgdbport = malloc(strlen(tmp) + 1);
if (pgdbport != NULL) {
dbport_alloc = 1;
strcpy(pgdbport,tmp);
} else {
ast_log(LOG_ERROR,"Out of memory error.\n");
return -1;
}
} else {
ast_log(LOG_WARNING,"PostgreSQL database port not specified. Using default 5432.\n");
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)
ast_log(LOG_DEBUG,"cdr_pgsql: got sock file of %s\n",pgdbsock);
ast_log(LOG_DEBUG,"cdr_pgsql: got user of %s\n",pgdbuser);
ast_log(LOG_DEBUG,"cdr_pgsql: got dbname of %s\n",pgdbname);
ast_log(LOG_DEBUG,"cdr_pgsql: got password of %s\n",pgpassword);
conn = PQsetdbLogin(pghostname, pgdbport, NULL, NULL, pgdbname, pgdbuser, pgpassword);
if (PQstatus(conn) != CONNECTION_BAD) {
ast_log(LOG_DEBUG,"Successfully connected to PostgreSQL database.\n");
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: Reason: %s\n", pgerror);
connected = 0;
}
res = ast_cdr_register(name, desc, pgsql_log);
if (res) {
ast_log(LOG_ERROR, "Unable to register PGSQL CDR handling\n");
}
return res;
}
int load_module(void)
{
return my_load_module();
}
int unload_module(void)
{
return my_unload_module();
}
int reload(void)
{
my_unload_module();
return my_load_module();
}
int usecount(void)
{
return connected;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

1577
channel.c

File diff suppressed because it is too large Load Diff

View File

@@ -11,86 +11,37 @@
# the GNU General Public License
#
OSARCH=$(shell uname -s)
USE_MYSQL_FRIENDS=0
CHANNEL_LIBS=chan_modem.so chan_iax.so chan_sip.so \
chan_modem_aopen.so \
chan_modem_bestdata.so chan_modem_i4l.so \
chan_agent.so chan_mgcp.so chan_iax2.so \
chan_local.so chan_skinny.so
#
# If you really want VoFR you can have it :-P
#
#CHANNEL_LIBS+=chan_vofr
ifneq (${OSARCH},Darwin)
CHANNEL_LIBS+=chan_oss.so
endif
CHANNEL_LIBS=chan_vofr.so chan_modem.so \
chan_modem_aopen.so chan_iax.so chan_oss.so \
chan_modem_bestdata.so chan_modem_i4l.so
CHANNEL_LIBS+=$(shell [ -f /usr/include/linux/ixjuser.h ] && echo chan_phone.so)
CHANNEL_LIBS+=$(shell [ -f h323/libchanh323.a ] && echo chan_h323.so)
CFLAGS+=-Wno-missing-prototypes -Wno-missing-declarations
CFLAGS+=$(shell [ ! -f /usr/include/linux/if_wanpipe.h ] && echo " -DOLD_SANGOMA_API")
CHANNEL_LIBS+=$(shell [ -f /usr/include/alsa/asoundlib.h ] && echo "chan_alsa.so")
CFLAGS+=$(shell [ -f /usr/lib/libpri.so.1 ] && echo " -DZAPATA_PRI")
CFLAGS+=$(shell [ -f /usr/lib/libmfcr2.so.1 ] && echo " -DZAPATA_R2")
CFLAGS+=$(shell [ -f alsa-monitor.h ] && echo " -DALSA_MONITOR")
ZAPPRI=$(shell [ -f /usr/lib/libpri.so.1 ] && echo "-lpri")
ZAPR2=$(shell [ -f /usr/lib/libmfcr2.so.1 ] && echo "-lmfcr2")
CFLAGS+=$(shell [ -f /usr/include/linux/zaptel.h ] && echo "-DIAX_TRUNKING")
CHANNEL_LIBS+=$(shell [ -f /usr/include/vpbapi.h ] && echo "chan_vpb.so" )
ALSA_SRC=chan_alsa.c
ALSA_SRC+=$(shell [ -f alsa-monitor.h ] && echo "alsa-monitor.h")
CFLAGS+=-DCRYPTO
CFLAGS+=-fPIC
ifeq ($(USE_MYSQL_FRIENDS),1)
CFLAGS+=-DMYSQL_FRIENDS
endif
CFLAGS+=#-DVOFRDUMPER
ZAPDIR=/usr/lib
CHANNEL_LIBS+=$(shell [ -f /usr/include/linux/zaptel.h ] && echo "chan_zap.so")
CHANNEL_LIBS+=$(shell [ -f $(ZAPDIR)/libzap.a ] && echo "chan_zap.so")
CHANNEL_LIBS+=$(shell [ -f /usr/include/nbs.h ] && echo "chan_nbs.so" )
CFLAGS+=$(shell [ -f $(ZAPDIR)/libzap.a ] && echo "-I$(ZAPDIR)")
ifndef OPENH323DIR
OPENH323DIR=$(HOME)/openh323
endif
ifndef PWLIBDIR
PWLIBDIR=$(HOME)/pwlib
endif
#CFLAGS+=$(shell [ -f $(ZAPDIR)/libzap.a ] && echo "-I$(ZAPDIR)")
all: depend $(CHANNEL_LIBS)
all: $(CHANNEL_LIBS)
clean:
rm -f *.so *.o .depend
rm -f busy.h ringtone.h gentone gentone-ulaw
rm -f *.so *.o
rm -f busy.h ringtone.h gentone
%.so : %.o
$(CC) $(SOLINK) -o $@ $<
ifneq ($(wildcard .depend),)
include .depend
endif
$(CC) -shared -Xlinker -x -o $@ $<
gentone: gentone.c
$(CC) -o gentone gentone.c -lm
gentone-ulaw: gentone-ulaw.c
$(CC) -o gentone-ulaw gentone-ulaw.c -lm
busy.h: gentone
./gentone busy 480 620
@@ -99,58 +50,11 @@ ringtone.h: gentone
chan_oss.o: chan_oss.c busy.h ringtone.h
ifeq (${OSARCH},OpenBSD)
chan_oss.so: chan_oss.o
$(CC) $(SOLINK) -o $@ chan_oss.o -lossaudio
endif
chan_iax2.so: chan_iax2.o iax2-parser.o
ifeq ($(USE_MYSQL_FRIENDS),1)
$(CC) $(SOLINK) -o $@ chan_iax2.o iax2-parser.o -lmysqlclient -lz
else
$(CC) $(SOLINK) -o $@ chan_iax2.o iax2-parser.o
endif
chan_iax.so: chan_iax.o
ifeq ($(USE_MYSQL_FRIENDS),1)
$(CC) $(SOLINK) -o $@ chan_iax.o -lmysqlclient -lz
else
$(CC) $(SOLINK) -o $@ chan_iax.o
endif
chan_zap.o: chan_zap.c
$(CC) -c $(CFLAGS) -o chan_zap.o chan_zap.c
chan_zap.so: chan_zap.o
$(CC) $(SOLINK) -o $@ $< $(ZAPPRI) $(ZAPR2) -ltonezone
chan_alsa.o: $(ALSA_SRC)
chan_alsa.so: chan_alsa.o
$(CC) $(SOLINK) -o $@ $< -lasound -lm -ldl
chan_nbs.so: chan_nbs.o
$(CC) $(SOLINK) -o $@ $< -lnbs
chan_vpb.o: chan_vpb.c
$(CXX) -c $(CFLAGS) -o $@ chan_vpb.c
chan_vpb.so: chan_vpb.o
$(CXX) $(SOLINK) -o $@ $< -lvpb -lpthread -lm -ldl
chan_h323.so: chan_h323.o h323/libchanh323.a
$(CC) $(SOLINK) -o $@ $< h323/libchanh323.a -L$(PWLIBDIR)/lib -lpt_linux_x86_r -L$(OPENH323DIR)/lib -lh323_linux_x86_r -L/usr/lib -lpthread -ldl -lcrypto -lssl -lexpat
$(CC) -shared -Xlinker -x -o $@ $< $(ZAPPRI) -lzap -ltonezone
#chan_modem.so : chan_modem.o
# $(CC) -rdynamic -shared -Xlinker -x -o $@ $<
install: all
for x in $(CHANNEL_LIBS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
depend: .depend
.depend:
../mkdep $(CFLAGS) `ls *.c`
for x in $(CHANNEL_LIBS); do $(INSTALL) -m 755 $$x $(MODULES_DIR) ; done

View File

@@ -80,7 +80,7 @@ struct vofr_hdr {
u_int8_t cid; /* Channel ID */
u_int8_t mod:4; /* Modulation */
u_int8_t remid:4; /* Remote ID */
#elif __BYTE_ORDER == __BIG_ENDIAN
#elif __BYTE__ORDER == __BIG_ENDIAN
u_int8_t ctag:4; /* Connect tag */
u_int8_t dtype:4; /* Data type */
u_int8_t vflags:4; /* Voice Routing Flags */

View File

@@ -23,7 +23,7 @@
// table to convert unsigned a-law bytes to signed linear integers
static const int alaw2int[256] = {
const int alaw2int[256] = {
-5504,5504,-344,344,-22016,22016,-1376,1376,-2752,2752,-88,88,-11008,11008,
-688,688,-7552,7552,-472,472,-30208,30208,-1888,1888,-3776,3776,-216,216,
-15104,15104,-944,944,-4480,4480,-280,280,-17920,17920,-1120,1120,-2240,2240,
@@ -50,7 +50,7 @@ static const int alaw2int[256] = {
// shift the integer to be 12+1 bit first, then add 4096 to get
// the right index
static const unsigned char int2alaw[8192] = {
const unsigned char int2alaw[8192] = {
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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