mirror of
https://github.com/asterisk/asterisk.git
synced 2026-03-19 03:54:04 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
435a47f8ed | ||
|
|
af3d087c1a | ||
|
|
0be2a468a0 |
54
BUGS
54
BUGS
@@ -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
209
CHANGES
@@ -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
63
CREDITS
@@ -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 ===
|
||||
|
||||
|
||||
70
HARDWARE
70
HARDWARE
@@ -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
438
Makefile
@@ -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
38
README
@@ -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
|
||||
|
||||
3
SECURITY
3
SECURITY
@@ -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
331
acl.c
@@ -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
20
addmailbox
Normal 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
|
||||
|
||||
311
aescrypt.c
311
aescrypt.c
@@ -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
463
aeskey.c
@@ -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
|
||||
232
aestab.c
232
aestab.c
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
24
agi/Makefile
24
agi/Makefile
@@ -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`
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
161
agi/eagi-test.c
161
agi/eagi-test.c
@@ -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);
|
||||
}
|
||||
@@ -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
85
alaw.c
@@ -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
219
app.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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`
|
||||
|
||||
1571
apps/app_adsiprog.c
1571
apps/app_adsiprog.c
File diff suppressed because it is too large
Load Diff
1196
apps/app_agi.c
1196
apps/app_agi.c
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
198
apps/app_cut.c
198
apps/app_cut.c
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
316
apps/app_db.c
316
apps/app_db.c
@@ -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;
|
||||
}
|
||||
788
apps/app_dial.c
788
apps/app_dial.c
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
|
||||
298
apps/app_disa.c
298
apps/app_disa.c
@@ -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,¬ime) < 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,¬ime) < 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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
116
apps/app_flash.c
116
apps/app_flash.c
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
251
apps/app_macro.c
251
apps/app_macro.c
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
386
apps/app_qcall.c
386
apps/app_qcall.c
@@ -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;
|
||||
}
|
||||
1518
apps/app_queue.c
1518
apps/app_queue.c
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
104
apps/app_read.c
104
apps/app_read.c
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
742
apps/app_rpt.c
742
apps/app_rpt.c
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
3544
apps/app_voicemail.c
3544
apps/app_voicemail.c
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
287
apps/enter.h
287
apps/enter.h
@@ -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 };
|
||||
207
apps/leave.h
207
apps/leave.h
@@ -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 };
|
||||
739
ast_expr.y
739
ast_expr.y
@@ -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;
|
||||
}
|
||||
32
astconf.h
32
astconf.h
@@ -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
161
asterisk-ng-doxygen
Normal 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
1156
asterisk.c
File diff suppressed because it is too large
Load Diff
28
asterisk.h
28
asterisk.h
@@ -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
|
||||
|
||||
@@ -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`
|
||||
|
||||
680
astman/astman.c
680
astman/astman.c
@@ -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
368
astmm.c
@@ -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(®lock);
|
||||
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(®lock);
|
||||
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(®lock);
|
||||
reg = regions[hash];
|
||||
while(reg) {
|
||||
if (reg->data == ptr) {
|
||||
len = reg->len;
|
||||
break;
|
||||
}
|
||||
reg = reg->next;
|
||||
}
|
||||
ast_mutex_unlock(®lock);
|
||||
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(®lock);
|
||||
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(®lock);
|
||||
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(®lock);
|
||||
|
||||
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(®lock);
|
||||
|
||||
/* 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
|
||||
152
autoservice.c
152
autoservice.c
@@ -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;
|
||||
}
|
||||
277
callerid.c
277
callerid.c
@@ -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
58
cas.h
Normal 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
459
cdr.c
@@ -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;
|
||||
}
|
||||
}
|
||||
67
cdr/Makefile
67
cdr/Makefile
@@ -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`
|
||||
274
cdr/cdr_csv.c
274
cdr/cdr_csv.c
@@ -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;
|
||||
}
|
||||
492
cdr/cdr_odbc.c
492
cdr/cdr_odbc.c
@@ -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, ×tr, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->clid, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->src, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->dst, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->dcontext, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->channel, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->dstchannel, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->lastapp, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->lastdata, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 10, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &cdr->duration, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 11, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &cdr->billsec, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 12, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &cdr->disposition, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 13, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &cdr->amaflags, 0, NULL);
|
||||
SQLBindParameter(ODBC_stmt, 14, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->accountcode, 0, NULL);
|
||||
|
||||
if((loguniqueid != 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;
|
||||
}
|
||||
333
cdr/cdr_pgsql.c
333
cdr/cdr_pgsql.c
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
1115
channels/chan_alsa.c
1115
channels/chan_alsa.c
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
Reference in New Issue
Block a user