contrib/package: add asterisk14-xip package to prepare Asterisk/LuCI/UCI integration

This commit is contained in:
Jo-Philipp Wich 2009-01-07 23:27:28 +00:00
parent c8a2a3031b
commit deabf41b3f
36 changed files with 6497 additions and 0 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,4 @@
## startup options for /etc/init.d/asterisk
ENABLE_ASTERISK="yes"
OPTIONS=""

View file

@ -0,0 +1,125 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2006 OpenWrt.org
START=50
STOP=50
DEST=
OPTIONS=""
DEFAULT=$DEST/etc/default/asterisk
UCILIB=$DEST/usr/lib/asterisk/uci
EXTRAPARAM=$1
export EXTRA_COMMANDS="console check down"
export EXTRA_HELP="\
console Start asterisk console
check Test asterisk uci config
down Force asterisk to stop"
reboot_ata() {
cd /tmp
wget -q http://ata.lan/admin/reboot -O - >&- 2>&-
}
load_ucilib() . ${UCILIB}/asteriskuci
start_uci() {
load_ucilib
start_uci_asterisk $DEST
}
restart_uci() {
load_ucilib
restart_uci_asterisk $DEST
}
stop_uci() {
load_ucilib
stop_uci_asterisk $DEST
}
reload_uci() {
load_ucilib
reload_uci_asterisk "$DEST"
}
start() {
[ -f $DEFAULT ] && . $DEFAULT
case ${ENABLE_ASTERISK-no} in
uci) start_uci ;;
yes)
[ -d /var/run ] || mkdir -p /var/run
[ -d $DEST/var/log/asterisk ] || mkdir -p $DEST/var/log/asterisk
[ -d $DEST/var/spool/asterisk ] || mkdir -p $DEST/var/spool/asterisk
[ -d /var/spool/asterisk ] || mkdir -p /var/spool/asterisk
[ -h $DEST/usr/lib/asterisk/astdb ] || ln -sf /var/spool/asterisk/astdb $DEST/usr/lib/asterisk/astdb
$DEST/usr/sbin/asterisk $OPTIONS -f 2>&1 > $DEST/var/log/asterisk/asterisk_proc &
( sleep 5; reboot_ata ) &
;;
*) return 1 ;;
esac
}
stop() {
[ -f $DEFAULT ] && . $DEFAULT
case ${ENABLE_ASTERISK} in
uci) stop_uci ;;
*) [ -f /var/run/asterisk.pid ] && kill $(cat /var/run/asterisk.pid) 2>&- >&-
esac
}
console() {
[ -f $DEFAULT ] && . $DEFAULT
case ${ENABLE_ASTERISK} in
uci) $DEST/usr/sbin/asterisk $UCIOPTIONS -C /tmp/asterisk/asterisk.conf -r ;;
yes) $DEST/usr/sbin/asterisk $OPTIONS -r ;;
esac
}
check() {
load_ucilib
setup_asterisk "$DEST" test "$EXTRAPARAM"
}
reload() {
[ -f $DEFAULT ] && . $DEFAULT
case ${ENABLE_ASTERISK-no} in
uci) reload_uci ;;
yes) restart ;;
esac
}
restart() {
[ -f $DEFAULT ] && . $DEFAULT
case ${ENABLE_ASTERISK-no} in
uci) restart_uci ;;
yes)
if [ -r /var/run/asterisk.ctl ] ; then
if $DEST/usr/sbin/asterisk -r -x "restart gracefully" 2>&- >&- ; then
echo "Restarting when convenient"
return 0
fi
fi
stop
start
esac
}
down() {
if [ -r /var/run/asterisk.ctl ] ; then
[ -f $DEFAULT ] && . $DEFAULT
case ${ENABLE_ASTERISK} in
uci) $DEST/usr/sbin/asterisk -C /tmp/asterisk/asterisk.conf -r -x "stop now" 2>&- >&- ;;
*) $DEST/usr/sbin/asterisk $OPTIONS -r -x "stop now" 2>&- >&-
esac
[ -f /var/run/asterisk.pid ] && sleep 1
fi
[ -f /var/run/asterisk.pid ] && kill $(cat /var/run/asterisk.pid) 2>&- >&-
[ -f /var/run/asterisk.pid ] && sleep 2
[ -f /var/run/asterisk.pid ] && kill -9 $(cat /var/run/asterisk.pid) 2>&- >&-
}
# vim:ts=2 sw=2

View file

@ -0,0 +1,23 @@
; Talking clock by Michael Geddes
; Borrowed from bits here and there.
[macro-talkingclock] ; (TimeFormat, DateFormat, Zone)
exten => s,1,Answer
exten => s,n,set(tcTimeFormat=${ARG1})
exten => s,n,GotoIf($["${tcTimeFormat}" = ""]?:tfOK)
exten => s,n,set(tcTimeFormat=HM\'vm-and\'S\'seconds\')
exten => s,n(tfOK),set(tcDateFormat=${ARG2})
exten => s,n,GotoIf($["${tcDateFormat}" = ""]?:dfOK)
exten => s,n,set(tcDateFormat=AdBY)
exten => s,n(dfOK),set(tcZone=${ARG3})
exten => s,n,GotoIf($["${tcZone}" = ""]?:znOK)
exten => s,n,set(tcZone=${TalkingClockZone})
exten => s,n(znOK),SayUnixTime(,${tcZone},${tcDateFormat})
exten => s,n(again),Wait(2)
exten => s,n,Set(FutureTime=$[${EPOCH} + 6])
exten => s,n,Playback(misc/at-tone-time-exactly)
exten => s,n,SayUnixTime(${FutureTime},${tcZone},${tcTimeFormat})
; Wait to say the beep.
exten => s,n(waitforit),noop
exten => s,n,GotoIf($[ ${EPOCH} < ${FutureTime} ]?waitforit:)
exten => s,n,playback(beep)
exten => s,n,goto(again)

View file

@ -0,0 +1,78 @@
; Last-Called number storage and calling.
; Author: Michael Geddes aka FrogOnWheels
[macro-lastcallstore] ; (Number , EntryType, BufferSize)
exten => s,1,set(lcsName=lastcall)
exten => s,n,set(lcsCount=10)
exten => s,n,GotoIf($["${ARG2}" = ""]?blankarg)
exten => s,n,GotoIf($["${ARG2}" = "lastcall"]?blankarg)
exten => s,n,Set(lcsName=lastcall_${ARG2})
exten => s,n(blankarg),GotoIf($["${ARG3}" = ""]?nocount)
exten => s,n,Set(lcsCount=${ARG3})
exten => s,n(nocount),Noop(${lcsName}:${DB(${lcsName}/number1)}:${ARG1})
exten => s,n,GotoIf($["${DB(${lcsName}/number1)}" = "${ARG1}"]?setdate)
exten => s,n,set(CallerPointer=1)
exten => s,n(again),GotoIf($["${DB(${lcsName}/ddate${CallerPointer})}" = ""]?copynext)
exten => s,n,GotoIf($["${DB(${lcsName}/number${CallerPointer})}" = "${ARG1}"]?copynext)
exten => s,n,Set(CallerPointer=$[${CallerPointer}+1])
exten => s,n,GotoIf($[${CallerPointer} <= ${lcsCount}]?again)
exten => s,n(copynext),set(DB(${lcsName}/ddate$[${CallerPointer}])=${DB(${lcsName}/ddate$[${CallerPointer}-1])})
exten => s,n,set(DB(${lcsName}/number$[${CallerPointer}])=${DB(${lcsName}/number$[${CallerPointer}-1])})
exten => s,n,set(CallerPointer=$[${CallerPointer}-1])
exten => s,n,GotoIf($[${CallerPointer} > 0]?copynext)
exten => s,n,set(DB(${lcsName}/number1)=${ARG1})
exten => s,n(setdate),set(DB(${lcsName}/ddate1)=${EPOCH})
[macro-lastcallapp] ; (Entrytype, Count, RingContext, Tag)
exten => s,1,set(lcsName=lastcall)
exten => s,n,set(lcsCount=10)
exten => s,n,GotoIf($["${ARG1}" = ""]?blankName)
exten => s,n,Set(lcsName=lastcall_${ARG1})
exten => s,n(blankName),GotoIf($["${ARG2}" = ""]?nocount)
exten => s,n,Set(lcsCount=${ARG2})
exten => s,n(nocount),set(lcsCallContext=internal)
exten => s,n,GotoIf($["${ARG3}" = ""]?blankContext)
exten => s,n,Set(lcsCallContext=${ARG3})
exten => s,n(blankContext),set(lcsTag=${ARG4})
exten => s,n,GotoIf($["${lcsTag}" != ""]?hasTag)
exten => s,n,Set(lcsTag=lastcall/previous-numbers)
exten => s,n(hasTag),Set(lcsPointer=1)
exten => s,n,GotoIf($["${DB(${lcsName}/ddate1)}" != ""]?macrobody_lastcallapp|s|1)
exten => s,n,playback(${lcsTag}&lastcall/none-available)
[macrobody_lastcallapp]
exten => s,1(repeat),background(${lcsTag})
exten => s,n(again),wait(1)
exten => s,n,Set(lcsLastnum=${DB(${lcsName}/number${lcsPointer})})
exten => s,n,Set(ddate=${DB(${lcsName}/ddate${lcsPointer})})
exten => s,n,GotoIf($["${lcsLastnum}" != "anonymous"]?checkblank)
exten => s,n,Set(lcsLastnum="")
exten => s,n(checkblank),GotoIf($["${lcsLastnum}" = ""]?noinfo)
exten => s,n,saydigits(${lcsLastnum})
exten => s,n(saycalltime),wait(.5)
exten => s,n,sayunixtime(${ddate},${LASTCALLZONE},QIMp)
exten => s,n(saymenu),background(silence/1)
exten => s,n,Set(lcsLastDate=${DB(${lcsName}/ddate$[ ${lcsPointer} + 1])})
exten => s,n,GotoIf($[$[${lcsPointer} = ${lcsCount}] | $["${lcsLastDate}" = ""]]?noprev)
exten => s,n,background(lastcall/next)
exten => s,n(noprev),GotoIf($["${lcsLastnum}" = ""]?nocall)
exten => s,n,background(lastcall/call-number)
exten => s,n(nocall),GotoIf($[${lcsPointer} = 1]?nonext)
exten => s,n,background(lastcall/previous)
exten => s,n(nonext),background(silence/10)
exten => s,n,Goto(repeat)
exten => s,n(noinfo),background(lastcall/no-number-info)
exten => s,n,goto(saycalltime)
exten => 5,1,GotoIf($["${lcsLastnum}" = ""]?noinfo])
exten => 5,n,Ringing()
exten => 5,n,Goto(${lcsCallContext},${lcsLastnum},1)
exten => 6,1,GotoIf($[$[${lcsPointer} = ${lcsCount}] | $["${lcsLastDate}" = ""]]?sayn)
exten => 6,n,Set(lcsPointer=$[${lcsPointer} + 1])
exten => 4,1,GotoIf($[${lcsPointer}=1]?sayn)
exten => 4,n,Set(lcsPointer=$[${lcsPointer} - 1])
exten => _[46],n(sayn),saynumber(${lcsPointer})
exten => _[46],n,goto(s|again)
exten => i,1,Goto(s|again)
exten => t,1,playback(goodbye)
exten => t,n,Hangup

View file

@ -0,0 +1,137 @@
;
; Asterisk configuration file
;
; Module Loader configuration file
;
[modules]
autoload=yes
;
; Any modules that need to be loaded before the Asterisk core has been
; initialized (just after the logger has been initialized) can be loaded
; using 'preload'. This will frequently be needed if you wish to map all
; module configuration files into Realtime storage, since the Realtime
; driver will need to be loaded before the modules using those configuration
; files are initialized.
;
; An example of loading ODBC support would be:
;preload => res_odbc.so
;preload => res_config_odbc.so
;
noload => res_config_mysql.so ;
noload => res_crypto.so ; Cryptographic Digital Signatures
; load => res_features.so ; Call Parking Resource
noload => res_indications.so ; Indications Configuration
noload => res_monitor.so ; Call Monitoring Resource
; load => res_musiconhold.so ; Music On Hold Resource
noload => cdr_csv.so ; Comma Separated Values CDR Backend
noload => cdr_custom.so ; Customizable Comma Separated Values CDR Backend
noload => cdr_manager.so ; Asterisk Call Manager CDR Backend
noload => cdr_mysql.so ; MySQL CDR Backend
noload => cdr_pgsql.so ; PostgreSQL CDR Backend
noload => cdr_sqlite.so ; SQLite CDR Backend
noload => chan_alsa.so ; Channel driver for GTalk
noload => chan_agent.so ; Agent Proxy Channel
noload => chan_gtalk.so ; Channel driver for GTalk
; load => chan_iax2.so ; Inter Asterisk eXchange (Ver 2)
; load => chan_local.so ; Local Proxy Channel
; load => chan_sip.so ; Session Initiation Protocol (SIP)
noload => codec_a_mu.so ; A-law and Mulaw direct Coder/Decoder
noload => codec_adpcm.so ; Adaptive Differential PCM Coder/Decoder
noload => codec_alaw.so ; A-law Coder/Decoder
noload => codec_g726.so ; ITU G.726-32kbps G726 Transcoder
; load => codec_gsm.so ; GSM/PCM16 (signed linear) Codec Translation
; load => codec_ulaw.so ; Mu-law Coder/Decoder
noload => codec_speex.so ; Speex/PCM16 (signed linear) Codec Translator
noload => format_au.so ; Sun Microsystems AU format (signed linear)
noload => format_g723.so ; G.723.1 Simple Timestamp File Format
noload => format_g726.so ; Raw G.726 (16/24/32/40kbps) data
noload => format_g729.so ; Raw G729 data
; load => format_gsm.so ; Raw GSM data
noload => format_h263.so ; Raw h263 data
noload => format_jpeg.so ; JPEG (Joint Picture Experts Group) Image
; load => format_pcm.so ; Raw uLaw 8khz Audio support (PCM)
noload => format_pcm_alaw.so ; Raw aLaw 8khz PCM Audio support
noload => format_sln.so ; Raw Signed Linear Audio support (SLN)
noload => format_vox.so ; Dialogic VOX (ADPCM) File Format
; load => format_wav.so ; Microsoft WAV format (8000hz Signed Line
; load => format_wav_gsm.so ; Microsoft WAV format (Proprietary GSM)
noload => app_alarmreceiver.so ; Alarm Receiver Application
noload => app_authenticate.so ; Authentication Application
noload => app_cdr.so ; Make sure asterisk doesn't save CDR
noload => app_chanisavail.so ; Check if channel is available
noload => app_chanspy.so ; Listen in on any channel
noload => app_controlplayback.so ; Control Playback Application
noload => app_cut.so ; Cuts up variables
noload => app_db.so ; Database access functions
; load => app_dial.so ; Dialing Application
noload => app_dictate.so ; Virtual Dictation Machine Application
noload => app_directory.so ; Extension Directory
noload => app_directed_pickup.so ; Directed Call Pickup Support
noload => app_disa.so ; DISA (Direct Inward System Access) Application
noload => app_dumpchan.so ; Dump channel variables Application
; load => app_echo.so ; Simple Echo Application
noload => app_enumlookup.so ; ENUM Lookup
noload => app_eval.so ; Reevaluates strings
noload => app_exec.so ; Executes applications
noload => app_externalivr.so ; External IVR application interface
noload => app_forkcdr.so ; Fork The CDR into 2 seperate entities
noload => app_getcpeid.so ; Get ADSI CPE ID
noload => app_groupcount.so ; Group Management Routines
noload => app_ices.so ; Encode and Stream via icecast and ices
noload => app_image.so ; Image Transmission Application
noload => app_lookupblacklist.so ; Look up Caller*ID name/number from black
noload => app_lookupcidname.so ; Look up CallerID Name from local databas
; load => app_macro.so ; Extension Macros
noload => app_math.so ; A simple math Application
noload => app_md5.so ; MD5 checksum Application
; load => app_milliwatt.so ; Digital Milliwatt (mu-law) Test Application
noload => app_mixmonitor.so ; Record a call and mix the audio during the recording
noload => app_parkandannounce.so ; Call Parking and Announce Application
; load => app_playback.so ; Trivial Playback Application
noload => app_privacy.so ; Require phone number to be entered
noload => app_queue.so ; True Call Queueing
noload => app_random.so ; Random goto
noload => app_read.so ; Read Variable Application
noload => app_readfile.so ; Read in a file
noload => app_realtime.so ; Realtime Data Lookup/Rewrite
noload => app_record.so ; Trivial Record Application
; load => app_sayunixtime.so ; Say time
noload => app_senddtmf.so ; Send DTMF digits Application
noload => app_sendtext.so ; Send Text Applications
noload => app_setcallerid.so ; Set CallerID Application
noload => app_setcdruserfield.so ; CDR user field apps
noload => app_setcidname.so ; Set CallerID Name
noload => app_setcidnum.so ; Set CallerID Number
noload => app_setrdnis.so ; Set RDNIS Number
noload => app_settransfercapability.so ; Set ISDN Transfer Capability
noload => app_sms.so ; SMS/PSTN handler
noload => app_softhangup.so ; Hangs up the requested channel
noload => app_stack.so ; Stack Routines
noload => app_system.so ; Generic System() application
noload => app_talkdetect.so ; Playback with Talk Detection
noload => app_test.so ; Interface Test Application
noload => app_transfer.so ; Transfer
noload => app_txtcidname.so ; TXTCIDName
noload => app_url.so ; Send URL Applications
noload => app_userevent.so ; Custom User Event Application
; load => app_verbose.so ; Send verbose output
noload => app_waitforring.so ; Waits until first ring after time
noload => app_waitforsilence.so ; Wait For Silence Application
noload => app_while.so ; While Loops and Conditional Execution
noload => func_callerid.so ; Caller ID related dialplan functions
noload => func_enum.so ; ENUM Functions
noload => func_uri.so ; URI encoding / decoding functions
noload => pbx_ael.so ; Asterisk Extension Language Compiler
; load => pbx_config.so ; Text Extension Configuration
noload => pbx_functions.so ; Builtin dialplan functions
noload => pbx_loopback.so ; Loopback Switch
noload => pbx_realtime.so ; Realtime Switch
noload => pbx_spool.so ; Outgoing Spool Support
noload => pbx_wilcalu.so ; Wil Cal U (Auto Dialer)
;
; Module names listed in "global" section will have symbols globally
; exported to modules loaded after them.
;
[global]
chan_modem.so=no

View file

@ -0,0 +1,144 @@
#!/bin/sh
# Asterisk.conf
init_asteriskconf() {
ast_add_reload dialplan
ast_enable_type asterisk
ast_enable_type setglobal
ast_enable_type include
# ast_enable_type hardware
ast_enable_type hardwarereboot
asterisk_zone="Australia/Perth"
asterisk_spooldir="${DEST}/var/spool/asterisk"
asterisk_logdir="${DEST}/var/log/asterisk"
asterisk_agidir="${DEST}/usr/lib/asterisk/agi-bin"
return 0
}
asterisk_option_list="verbose debug quiet dontwarn timestamp execincludes \
highpriority initcrypto nocolor dumpcore languageprefix internal_timing \
systemname maxcalls maxload cache_record_files record_cache_dir \
transmit_silence_during_record transcode_via_sln runuser rungroup"
asterisk_path_list="spooldir logdir agidir"
valid_asterisk_option() {
is_in_list $1 ${asterisk_option_list} ${asterisk_path_list} zone
return $?
}
create_asteriskconf() {
# echo ${DEST_DIR}
file=${DEST_DIR}/asterisk.conf
get_checksum asterisk_conf $file
echo "${asteriskuci_gen}${N}[directories]
astetcdir => ${DEST_DIR}
astmoddir => ${DEST}/usr/lib/asterisk/modules
astvarlibdir => ${DEST}/usr/lib/asterisk
astdatadir => ${DEST}/usr/lib/asterisk
astrundir => /var/run" > $file
for i in ${asterisk_path_list} ; do
eval "value=\"\${asterisk_$i}\""
if [ ! -z $value ] ; then
echo "ast$i => $value" >> $file
fi
done
echo "${N}[options]" >> $file
for i in ${asterisk_option_list} ; do
eval "value=\"\${asterisk_$i}\""
if [ ! -z $value ] ; then
echo "$i => $value" >> $file
fi
done
echo "${N}; Changing the following lines may compromise your security.
[files]
astctlpermissions = 0660
astctlowner = root
astctlgroup = nogroup
astctl = asterisk.ctl " >> $file
check_checksum "$asterisk_conf" "$file" || ast_restart=1
}
handle_asterisk() {
option_cb() {
case $1 in
zone)
asterisk_zone="$2";;
*)
if valid_asterisk_option $1 $2 ; then
eval "asterisk_${1}=\"$2\""
else
logerror "Invalid Asterisk option: $1"
fi
esac
}
}
handle_include(){
option_cb() {
case $1 in
dialplan|dialplan_ITEM*)
append dialplan_includes "#include <$2>" "${N}"
;;
dialplan_COUNT) ;;
*) logerror "Invalid option \"$1\" for include" ;;
esac
}
}
handle_setglobal() {
option_cb() {
case $1 in
set_COUNT) ;;
set|set_ITEM*)
if [ "${2%=*}" == "${2}" ] ; then
logerror "SetGlobal option \"$2\" not of the form VARIABLE=Value"
else
append dialplan_globals "" "${N}"
fi ;;
*) logerror "Invalid option \"$1\" for setglobal" ;;
esac
}
}
handle_hardwarereboot() handle_hardware reboot
# Handle hardware options (reboot) for Softphones
handle_hardware() {
case $1 in
reboot)
hardware_method=
hardware_param=
option_cb() {
case $1 in
method)
hardware_method="$2";;
param)
case ${hardware_method} in
web) append hardware_reboots "wget -q $2 -O - >&- 2>&-" "${N}" ;;
system) append hardware_reboots "$2 >&- 2>&-" "${N}" ;;
*) logerror "Invalid Hardware reboot method: ${hardware_method}"
esac
esac
}
;;
*) logerror "Invalid Hardware option: $1"
esac
}
reboot_hardware() {
cd /tmp
eval ${hardware_reboots}
}
# vim: ts=2 sw=2 noet foldmethod=indent

View file

@ -0,0 +1,41 @@
asterisk
zone - Default TimeZone
Various asterisk.conf options
verbose
debug
quiet
dontwarn
timestamp
execincludes
highpriority
initcrypto
nocolor
dumpcore
languageprefix
internal_timing
systemname
maxcalls
maxload
cache_record_files
record_cache_dir
transmit_silence_during_record
transcode_via_sln
runuser
rungroup
spooldir
logdir
agidir
setglobal
set (list) - VARIABLE=Value Global Variables
include
dialplan (list) - Files to #include
hardwarereboot - Reboot phone hardware
method - web (wget), system
param - url/program for reboot

View file

@ -0,0 +1,365 @@
#!/bin/sh
# Author: Michael Geddes <michael at frog dot wheelycreek dot net>
# Copyright 2008 Michael Geddes
# Licensed under GPL
Version=0.8
# Todo
# Calling of Macros in dialplan
# Create a Menu
# Incoming Zones
debuglevel=0
. /etc/functions.sh
asteriskuci_gen="; Generated by Openwrt AstriskUCI script version ${Version}$N"
# Utils
logerror() {
echo "Error: $1"
}
logdebug() {
if [ $(expr $1 "<=" ${debuglevel-0}) == 1 ] ; then
echo "Log: $2"
fi
}
is_in_list(){
val=$1
shift
for i in $* ; do
[ $i == $val ] && return 0
done
return 1
}
split_append() {
local lhs="$2"
local rhs="$3"
while [ ! -z "$rhs" ] ; do
cur=${rhs%%,*}
nvar=${rhs#*,}
[ -z $4 ] || eval "$4 ${cur}"
append $1 "${lhs}${cur}" "$4"
[ "$nvar" == "$rhs" ] && break
rhs=${nvar}
done
}
get_checksum() {
if [ -r "$2" ] ; then
local sum=`md5sum $2 | cut -d " " -f 1`
eval "$1=\"$sum\""
else
eval "$1=NONE"
fi
#eval "logdebug 1 \"Checksum $2 : \${$1}\""
}
check_checksum() {
if [ -r "$2" ] ; then
local sum=`md5sum $2 | cut -d " " -f 1`
else
eval sum=NONE
fi
#logdebug 1 "Compare $1 checksum $2 with new checksum $sum "
[ "$sum" == "$1" ]
return $?
}
# Add config module to initialise list
ast_add_conf() append asterisk_conf_list $1 " "
# Add module to initialise list
ast_add_module() append asterisk_module_list $1 " "
# Add to 'reload' list.
ast_add_reload() append asterisk_load_list $1 " "
# Enable a top-level type
ast_enable_type() eval "enabled_section_${1}=1"
# Is a top-level type enabled?
ast_type_enabled() {
eval "local res=\${enabled_section_${1}}"
if [ "$res" != 1 ] ; then
return 1 #Fail
fi
return 0
}
# For use in sections - make sure that the last section is processed
check_add() {
logdebug 1 "Check add $1"
if [ ! -z "${last_added_checked}" ] ; then
logdebug 1 "Eval check-add ${last_added_checked}"
eval "check_add_${last_added_checked}"
fi
last_added_checked=$1
}
# Process the section yet to be checked.
check_all_added() check_add ""
# Create static links for stuff we dont want to configure yet.
create_staticlinks() {
logdebug 1 "Link in a few mostly static configurations"
linkconfigs="codecs.conf say.conf sip_notify.conf udptl.conf logger.conf"
module_enabled res_indications && append linkconfigs indications.conf " "
for i in ${linkconfigs} ; do
[ -e $DEST_DIR/$i ] || ln -s $DEST/etc/asterisk/$i $DEST_DIR
done
logdebug 1 "Link in #include directories"
for i in include inc libs lib library macro macros ; do
if [ -e $DEST/etc/asterisk/$i -a ! -d "$DEST_DIR/$i" -a ! -e "$DEST_DIR/$i" ] ; then
ln -s $DEST/etc/asterisk/$i $DEST_DIR
fi
done
}
# default reboot
reboot_hardware() {}
# Top level handler
setup_asterisk() {
DEST=${1%/}
DEST_DIR=/tmp/asterisk
testing_mode=0
if [ "$2" == "testonly" ] ; then
testing_mode=1
elif [ "$2" == "test" ] ; then
DEST_DIR=/tmp/asterisk.tmp
echo Using Test dir: $DEST_DIR
testing_mode=2
fi
[ -z "$3" ] || debuglevel=$3
logdebug 1 "Loading Asterisk Config"
. ${UCILIB}/asteriskconf
logdebug 2 "Loading Module Config"
. ${UCILIB}/moduleconf
logdebug 2 "Loading Dialplan Config"
. ${UCILIB}/dialplanconf
for f in ${DEST}/etc/asterisk/conf.d/* ; do
logdebug 1 "Loading Module $f"
[ -f $f ] && . $f
done
include /lib/network
scan_interfaces
init_asteriskconf
init_moduleconf
init_dialplanconf
for i in ${asterisk_module_list} ; do
logdebug 1 "Init $i module"
eval "init_${i}"
done
for i in ${asterisk_conf_list} ; do
logdebug 1 "Init $i config"
eval "init_${i}conf"
done
config_cb() {
cur_section=$1/$2
logdebug 2 "Load $1/$2"
eval "local val=\"\${dups_$2}\""
if [ "${val}" == "" ] ; then
eval "dups_$2=1"
else
logerror "Duplicate Section Name: $2 (type $1)"
fi
if ast_type_enabled $1 ; then
eval "handle_$1 \$2"
elif [ ! -z "$1" ] ; then
logerror "Unknown section: $1/$2"
option_cb() {
logerror "Invalid option '$1' for invalid section"
}
fi
}
config_load asterisk
check_all_added
if [ "$testing_mode" != "1" ] ; then
mkdir -p ${DEST_DIR}
create_asteriskconf
for i in ${asterisk_conf_list} ; do
logdebug 1 "Create $i config"
eval "create_${i}conf"
done
create_dialplanconf
create_moduleconf
# Link in a few mostly static configurations
create_staticlinks
fi
[ "$testing_mode" == "2" ] && reload_check_asterisk
return 0
}
astcmd() {
ASTCMD="${DEST%/}/usr/sbin/asterisk -C /tmp/asterisk/asterisk.conf "
logdebug 1 "Command: $1"
if [ -z "${2-}" ] ; then
${ASTCMD} -r -x "$1" 2>&- 1>&-
else
eval "$2=`${ASTCMD} -r -x \"$1\"`"
fi
return $?
}
# waitfor() {
# while [ -d /proc/$1 ] ; do
# sleep 1
# done
# }
restart_gracefully() {
stop_uci_asterisk "$DEST"
startup_asterisk "$DEST"
#ret=0
#echo "Check for pid"
#if [ -r /var/run/asterisk.ctl ] ; then
# astcmd "stop gracefully"
# local ret=$?
# [ ${ret} = 0 ] || return $ret
# waitfor `cat /var/run/asterisk.pid`
#fi
#startup_asterisk ${DEST}
return 0
}
astcmds() {
while [ ! -z "$1" ] ; do
astcmd "$1"
shift
done
}
reload_check_asterisk() {
logdebug 1 "Check Reloading"
local reboot=0
if [ "${ast_restart-}" == 1 ] ; then
logdebug 1 "Restarting Gracefully"
reboot=0
else
for i in ${asterisk_load_list} ; do
logdebug 1 "Checking ${i} reload"
eval "local doload=\${ast_${i}_restart}"
case $doload in
1) logdebug 1 "Reloading ${i}" ;;
2) logdebug 1 "Unloading ${i}" ;;
esac
done
fi
[ ${reboot} = 1 ] && logdebug 1 "reboot hardware"
}
reload_asterisk() {
logdebug 1 "Reloading"
local reboot=0
if [ "${ast_restart-}" == 1 ] ; then
logdebug 2 "Restarting Gracefully"
restart_gracefully
reboot=0
else
for i in ${asterisk_load_list} ; do
logdebug 3 "Checking ${i} reload"
eval "local doload=\${ast_${i}_restart}"
case $doload in
1) logdebug 1 "Reloading ${i}"
eval "reload_${i}" || reboot=1 ;;
2) logdebug 1 "Unloading ${i}"
eval "unload_${i}" || reboot=1 ;;
esac
done
fi
if [ ${reboot} = 1 ] ; then
( sleep 5; reboot_hardware ) &
fi
}
startup_asterisk() {
DEST="${1%/}"
DEFAULT=$DEST/etc/default/asterisk
[ -f $DEFAULT ] && . $DEFAULT
[ -d /var/run ] || mkdir -p /var/run
[ -d ${asterisk_logdir} ] || mkdir -p ${asterisk_logdir}
[ -d ${asterisk_spooldir} ] || mkdir -p ${asterisk_spooldir}
[ -d /var/spool/asterisk ] || mkdir -p /var/spool/asterisk
[ -h $DEST/usr/lib/asterisk/astdb ] || ln -sf /var/spool/asterisk/astdb $DEST/usr/lib/asterisk/astdb
$DEST/usr/sbin/asterisk -C /tmp/asterisk/asterisk.conf $UCIOPTIONS -f 2>&1 > ${asterisk_logdir}/asterisk_proc &
# Wait a bit then reboot the hardware
( sleep 5; reboot_hardware ) &
}
# Init.d start() handler
start_uci_asterisk() {
DEST="${1%/}"
if setup_asterisk $DEST ; then
startup_asterisk "$DEST"
fi
}
restart_uci_asterisk() {
DEST="${1%/}"
if setup_asterisk $DEST ; then
echo "Trying to Restart gracefully"
if [ -r /var/run/asterisk.ctl ] ; then
# if astcmd "restart gracefully" ; then
echo "Sending restart"
if restart_gracefully ; then
echo "Restarting gracefully"
return 0
fi
fi
stop_uci_asterisk "$DEST"
startup_asterisk "$DEST"
else
stop_uci_asterisk $1
echo "Setup Failed"
return 1
fi
}
# init.d stop() handler
stop_uci_asterisk() {
DEST=${1%/}
if [ -r /var/run/asterisk.ctl ] ; then
astcmd "stop now"
sleep 1
fi
[ -f /var/run/asterisk.pid ] && kill $(cat /var/run/asterisk.pid) >/dev/null 2>&1
}
reload_uci_asterisk() {
DEST=${1%/}
DEFAULT=$DEST/etc/default/asterisk
if [ -r /var/run/asterisk.ctl ] ; then
if setup_asterisk "$DEST" ; then
# Selective reload modules.
reload_asterisk
fi
else
start_uci_asterisk "$1"
fi
}
# vim: ts=2 sw=2 noet foldmethod=indent

View file

@ -0,0 +1,742 @@
#!/bin/sh
# Dialplans (extensions.conf)
# Implicit: ast_add_conf dialplan
init_dialplanconf() {
ast_enable_type dialplangeneral
ast_enable_type dialplan
ast_enable_type dialplanexten
ast_enable_type dialplangoto
ast_enable_type dialplansaytime
ast_enable_type dialzone
ast_enable_type inzone
ast_enable_type incominggeneral
ast_enable_type incoming
dialplan_allowtransfer=no
dialplan_dialtimeout=30
dialplan_answerfirst=no
dialplan_static=yes
dialplan_writeprotect=no
dialplan_canreinvite=no
dialplan_includes=
dialplan_globals=
return 0
}
dialplangeneral_list="static writeprotect canreinvite clearglobalvars"
dialplangeneral_list_ex="lastdialed lastdialedtype voiceboxext answerfirst dialtimeout allowtransfer international internationalout"
valid_dialplangeneral() {
for i in ${dialplangeneral_list} ${dialplangeneral_list_ex} ; do
[ "$i" == "$1" ] && return 0
done
return 1
}
check_add_context() {
local context="${1}"
local check="${context#macro-}"
[ "${context}" == ${check} ] || check="macro__${check}"
eval "local isadded=\"\${dialplan_add_context_${check}-0}\""
if [ "$isadded" != "1" ] ; then
eval "dialplan_add_context_${check}=1"
append dialplan_contexts "$context"
return 0
else
return 1
fi
}
append_dialplan_context() {
local context="${1}"
local check="${context#macro-}"
[ "${context}" == ${check} ] || check="macro__${check}"
append dialplan_context_${check} "${2}" "${N}"
}
reload_dialplan() astcmd "dialplan reload"
# Voicemail
enable_voicemail() {
enable_module res_adsi
enable_module app_voicemail
enable_format gsm
}
add_dialplan_exten() {
local context=$1
logdebug 3 "Exten: $2"
local ext="exten => $2,"
local planopt=
local timeout=${dialplan_dialtimeout}
# Answer extensions first.
local answerfirst=${dialplan_answerfirst}
local mailbox=$4
[ -z "$5" ] || timeout=$5
[ -z "$6" ] || answerfirst=$6
check_add_context "$context"
if [ "$dialplan_allowtransfer" == "yes" ] ; then
planopt=${planopt}t
fi
if [ ! -z "${planopt}" ] ; then
planopt=",${timeout},${planopt}"
elif [ ! -z "${timeout}" ] ; then
planopt=",${timeout}"
fi
local dial="Dial($3$planopt)"
local item="1,"
if [ "$answerfirst" == "yes" ] ; then
append_dialplan_context ${context} "${ext}1,Answer"
item="n,"
fi
append_dialplan_context ${context} "${ext}${item}${dial}"
if [ ! -z "${mailbox}" ] ; then
enable_voicemail
append_dialplan_context ${context} "${ext}n,VoiceMail(${mailbox})"
fi
append_dialplan_context ${context} "${ext}n,Congestion"
}
add_dialplan_include() {
local context=$1
logdebug 1 "Adding Dialplan Include $1 $2"
check_add_context "$context"
split_append dialplan_context_${context} "include => " "$2" "${N}"
}
add_dialplan_saytime() {
local context=$1
logdebug 1 "Adding Dialplan saytime $1 $2"
check_add_context "$context"
local ext="exten => $2,"
if [ "$dialplan_add_context_saytime" != 1 ] ; then
append dialplan_contexts saytime " "
dialplan_add_context_saytime=1
enable_format gsm
enable_module app_sayunixtime
local zone=${asterisk_zone}
[ ! -z "$3" ] && zone="$3"
local format="IMp AdbY"
[ ! -z "$4" ] && format="$4"
append dialplan_context_saytime "exten => s,1,SayUnixTime(,${zone},${format})" "${N}"
fi
append_dialplan_context ${context} "${ext}1,Goto(saytime,s,1)"
}
add_dialplan_goto() {
local context=$1
logdebug 1 "Adding Dialplan goto $1 $2 $3"
check_add_context "$context"
append dialplan_context_${context} "exten => $2,1,Goto($3,\${EXTEN},1)" "${N}"
}
handle_inzone() {
# TODO - Incoming zones.
return 0
}
#generate_inzone() {
#[local_Vista]
#exten => _X.,1,Ringing()
#exten => _X.,n,Dial(SIP/Nokia,5)
#exten => _X.,n,Answer
#exten => _X.,n,wait(1)
#exten => _X.,n,Set(EXITCONTEXT=xyzzy)
#exten => _X.,n,Dial(SIP/Nokia,15,rd)
#exten => _X.,n,Hangup
#[xyzzy]
#exten => 1,1,Noop(xyzzy)
#exten => 1,n,SayAlpha(b)
#exten => 1,n,Hangup
#}
append_dialplan_dialzone() {
local file=$1
# Add the dialzone contexts
logdebug 1 "Dialplan: Add the dialzone contexts"
for zonename in ${dzones_match} ; do
eval "local diallist=\${dzone_${zonename}_match-}"
echo "${N}[${zonename}]" >> $file
eval "dialz=\${dzone_match_use_${zonename}-}"
for v in prefix internationalprefix alwaysinternational countrycode ; do
eval "local $v=\${target_${v}_${dialz}:-}"
eval logdebug 3 "\"${v} = '\${$v}'\""
done
for v in localzone addprefix localprefix; do
eval "local $v=\${dzone_${zonename}_${v}:-}"
done
while [ ! -z "$diallist" ] ; do
cur=${diallist%%,*}
nvar=${diallist#*,}
if [ "${alwaysinternational}" = "yes" ] ; then
# Always dial international number with this target
# remove 'localprefix' (usually 0) from 'addprefix'
logdebug 3 "Removing ${localprefix} from ${addprefix}"
addprefix=${addprefix#$localprefix}
local curlen=`expr length "${localprefix}"`
if [ $curlen != 0 ] ; then
# remove 0 (or local prefix)
echo "exten => _${localprefix}${cur},1,Goto(${dialz}_dial,${countrycode}${addprefix}\${EXTEN:$curlen},1)" >> $file
fi
echo "exten => _${cur},1,Goto(${dialz}_dial,${countrycode}${addprefix}\${EXTEN},1)" >> $file
else
echo "exten => _${cur},1,Goto(${dialz}_dial,${addprefix}\${EXTEN},1)" >> $file
fi
[ "$nvar" == "$diallist" ] && break
diallist=${nvar}
done
eval "local diallist=\${dzone_${zonename}_international-}"
if [ ! -z "${diallist}" ] ; then
logdebug 2 "International: ${diallist}"
while [ ! -z "$diallist" ] ; do
cur=${diallist%%,*}
nvar=${diallist#*,}
local curlen=`expr length ${cur}`
if [ "$alwaysinternational" = "yes" ] ; then
echo "exten => _${cur},1,Goto(${dialz}_dial,${addprefix}\${EXTEN:${curlen}},1)" >> $file
else
echo "exten => _${cur}.,1,Goto(${zonename}_check,${addprefix}\${EXTEN:${curlen}},1)" >> $file
fi
[ "$nvar" == "$diallist" ] && break
diallist=${nvar}
done
if [ "$alwaysinternational" != "yes" ] ; then
# Check for local country code
echo "[${zonename}_check]" >> $file
local locallen=`expr length ${countrycode}`
echo "exten => _${countrycode}X.,1,Goto(${localzone-default},${localprefix-0}\${EXTEN:${locallen}},1)" >> $file
echo "exten => _X.,1,Goto(${dialz}_dial,${internationalprefix}\${EXTEN},1)" >> $file
fi
fi
done
logdebug 1 "Dialplan: Finish the dialzone contexts"
}
append_dialplan_dialzone_out(){
local file=$1
# Add the dialzone target contexts (dialing out)
logdebug 1 "Dialplan: Add the dialzone target contexts"
for contype in SIP IAX ; do
eval local conlist=\${dzones_${contype}-}
logdebug 1 "Adding ${contype} targets: ${conlist}"
for conname in $conlist ; do
echo "${N}[${contype}_${conname}_dial]" >> $file
for v in prefix internationalprefix alwaysinternational countrycode timeout lastdialed lastdialedtype ; do
eval "local $v=\${target_${v}_${contype}_${conname}:-}"
done
if [ -z "${lastdialed}" ] ; then
lastdialed=${dialplan_lastdialed}
lastdialedtype=${dialplan_lastdialedtype}
fi
# [ -z "${lastcallout}" ] && lastcallout=${feature_lastcall_outqueue}
# if [ ! -z "${lastcalloutexten}" ] ; then
# eval "local added=\${lastcallout_outqueue_extension_${lastcalloutexten}}"
# if [ ! "${added}" == 1 ] ; then
# add_dialplan_lastcall extensions "${lastcalloutexten}" "${lastcallout}" "${feature_lastcall_outcount}"
# eval "local lastcallout_outqueue_extension_${lastcalloutexten}=1"
# fi
# fi
local ext="exten => _X.,"
local en="1,"
# Do not use prefix unles 'alwaysinternational' is yes
[ "$alwaysinternational" != "yes" ] && internationalprefix=
# if [ ! -z "${lastcallout}" ] ; then # Add lastcall out
# enable_lastcall
# echo "${ext}${en}Macro(lastcallstore,${internationalprefix}\${EXTEN},${lastcallout},${feature_lastcall_outcount})" >> $file
# en="n,"
# fi
if [ ! -z "${lastdialed}" ] ; then
enable_module func_callerid
local lastparam="\${EXTEN}"
local lastmacro=${lastdialed}
local lastmacrotype=${lastdialedtype}
[ -z ${lastdialedtype} ] && lastdialedtype=goto
local jumpmacroline=
gen_jumpmacro jumpmacroline "${ext}${en}" "" "${lastmacrotype}" "${lastmacro}" "${lastparam}"
echo ${jumpmacroline} >> $file
en="n,"
fi
echo "${ext}${en}Dial(${contype}/${prefix}${internationalprefix}\${EXTEN}@${conname},$timeout)" >> $file
echo "exten => _X.,n,Congestion" >> $file
done
done
}
gen_jumpmacro() {
logdebug 3 "Gen JumpMacro /$1/=/$2/$3/$4/$5/$6/"
local leader=$2
local condition=$3
local macrotype=$4
local name=$5
local param=$6
if [ -z "${condition}" ] ; then
local cond="("
else
local cond="If(${condition}?"
fi
case ${macrotype} in
gosub)
enable_module app_stack # for gosub
logdebug 1 "${1}=\"\${leader}Gosub\${cond}\${name},\${param},1)\""
eval "${1}=\"\${leader}Gosub\${cond}\${name},\${param},1)\"" ;;
gosub_s)
enable_module app_stack # for gosub
logdebug 1 "${1}=\"\${leader}Gosub\${cond}\${name},s,1(\${param}))\""
eval "${1}=\"\${leader}Gosub\${cond}\${name},s,1(\${param}))\"" ;;
macro)
enable_module app_macro
logdebug 1 "${1}=\"\${leader}Macro\${cond}\${name},\${param})\""
eval "${1}=\"\${leader}Macro\${cond}\${name},\${param})\"" ;;
s|start)
enable_module app_goto
logdebug 1 "${1}=\"\${leader}Goto(\${iz_target},s,1)\""
eval "${1}=\"\${leader}Goto(\${iz_target},s,1)\"" ;;
*)
enable_module app_goto
logdebug 1 "${1}=\"\${leader}Goto\${cond}\${name},\${param},1)\""
eval "${1}=\"\${leader}Goto\${cond}\${name},\${param},1)\"" ;;
esac
}
append_jumpmacro(){
local context=$1
local jumpmacroline=""
gen_jumpmacro "jumpmacroline" "$2" "$3" "$4" "$5" "$6"
append_dialplan_context ${context} "${jumpmacroline}"
}
append_dialplan_incoming(){
local file=$1
# Evaluate the incoming ringing dialplans
logdebug 1 "Add the 'incoming' dialplans: ${dialplan_extensions_incoming}"
for context in ${dialplan_extensions_incoming} ; do
eval "local curext=\"\${dialplan_incoming_$context}\""
logdebug 2 "Adding incoming ${curext}"
check_add_context "$context"
# lastcall lastcallexten lastmissed lastmissedexten
for i in answerfirst beforeanswer timeout menucontext \
lastcall lastcalltype missed missedtype allowtransfer mailbox match matchcaller aftertimeout aftertimeouttype; do
eval "local iz_$i=\"\${incoming_${context}_$i}\""
eval "logdebug 1 \"Incoming \$context: iz_\$i=\${iz_$i}\""
done
[ ! -z ${iz_menucontext} ] && iz_answerfirst=yes
if [ ! -z ${curext} ] ; then
[ -z ${iz_answerfirst} ] && iz_answerfirst=${incoming_answerfirst}
# [ -z ${iz_lastcall} ] && iz_lastcall=${feature_lastcall_inqueue}
if [ -z ${iz_lastcall} ] ; then
iz_lastcall=${incoming_lastcall}
iz_lastcalltype=${incoming_lastcalltype}
fi
if [ -z ${iz_missed} ] ; then
iz_missed=${incoming_missed}
iz_missedtype=${incoming_missedtype}
fi
[ -z ${iz_mailbox} ] && iz_mailbox=${incoming_mailbox}
[ -z ${iz_timeout} ] && iz_timeout=${incoming_timeout}
[ -z ${iz_allowtransfer} ] && iz_allowtransfer=${incoming_allowtransfer}
fi
[ -z ${iz_match} ] && iz_match=_X.
[ ! -z ${iz_matchcaller} ] && iz_match=${iz_match}/${iz_matchcaller}
local ext="exten => ${iz_match},"
local planopt=
[ "${iz_allowtransfer}" == "yes" ] && planopt=${planopt}t
local item="1,"
#append_dialplan_context ${context} "${ext}${item}Ringing()"
if [ ! -z "${iz_lastcall}" ] ; then
enable_module func_callerid
local lastparam="\${CALLERID(num)}"
local lastmacrotype="${iz_lastcalltype}"
[ -z "${iz_lastcalltype}" ] && lastmacrotype=goto
local lastmacro=${iz_lastcall}
append_jumpmacro "${context}" "${ext}${item}" "" "${lastmacrotype}" "${lastmacro}" "${lastparam}"
item="n,"
fi
if [ ! -z "${iz_missed}" ] ; then
enable_module func_callerid
local missedparam="\${CALLERID(num)}"
[ -z "${iz_missedtype}" ] && iz_missedtype=goto
append_dialplan_context ${context} "${ext}${item}Set(lcsMissed=\${CALLERID(num)})"
item="n,"
fi
# Ring before answering
if [ ! -z "${iz_beforeanswer}" -a ! -z "${curext}" ] ; then
append_dialplan_context ${context} "${ext}${item}Dial(${curext},${iz_beforeanswer},${planopt})"
iz_answerfirst=yes
item="n,"
fi
# Now answer
if [ "$iz_answerfirst" == "yes" ] ; then
append_dialplan_context ${context} "${ext}${item}Answer"
item="n,"
fi
# if [ ! -z ${iz_lastcallexten} ] ; then
# enable_lastcall
# add_dialplan_lastcall extensions "${iz_lastcallexten}" "${iz_lastcall}" "${feature_lastcall_incount}"
# fi
if [ ! -z ${curext} ] ; then
if [ ! -z ${iz_menucontext} ] ; then
planopt=${planopt}rd
enable_module res_indications
# wait so the next ring connects.
append_dialplan_context ${context} "${ext}${item}Wait(1)"
append_dialplan_context ${context} "${ext}n,Set(EXITCONTEXT=${iz_menucontext})"
fi
if [ ! -z ${planopt} ] ; then
planopt=",${iz_timeout-},${planopt}"
elif [ ! -z ${iz_timeout-} ] ; then
planopt=",${iz_timeout-}"
fi
local dial="Dial(${curext}${planopt})"
append_dialplan_context ${context} "${ext}n,${dial})"
if [ ! -z ${iz_missed} ] ; then
# It went to voicemail or was hung up - consider missed
append_jumpmacro ${context} "${ext}${item}" "" "${iz_missedtype}" "${iz_missed}" "\${lcsMissed}"
fi
fi
local need_hangup=1
# Add a goto or macro at the end
if [ ! -z ${iz_target} ] ; then
case ${iz_aftertimeouttype} in
macro) append_dialplan_context ${context} "${ext}${item}Macro(${iz_target})";;
s|start) append_dialplan_context ${context} "${ext}${item}Goto(${iz_target},s,1)"
need_hangup=0;;
*) append_dialplan_context ${context} "${ext}${item}Goto(${iz_target},\${EXTEN},1)"
need_hangup=0;;
esac
fi
if [ ! -z ${iz_mailbox} ] ; then
enable_voicemail
append_dialplan_context ${context} "${ext}n,VoiceMail(${iz_mailbox})"
fi
[ "${need_hangup}" = "1" ] && append_dialplan_context ${context} "${ext}n,Hangup"
if [ ! -z ${iz_missed} ] ; then
# Check for missed call
append_jumpmacro ${context} "exten => h,1," "\$[\"\${DIALSTATUS}\" = \"CANCEL\"]" "${iz_missedtype}" "${iz_missed}" "\${lcsMissed}"
#append dialplan_context_${context} \
# "exten => h,1,MacroIf(\$[\"\${DIALSTATUS}\" = \"CANCEL\"]?lastcallstore,\${lcsMissed},${iz_lastmissed},${feature_lastcall_incount})" "${N}"
# [ ! -z ${iz_lastmissedexten} ] && \
# add_dialplan_lastcall extensions "${iz_lastmissedexten}" "${iz_lastmissed}" "${feature_lastcall_incount}"
fi
done
}
append_dialplan_extensions(){
local file=$1
# Evaluate the 'extension' dialplans
logdebug 1 "Add the 'extension' dialplans: ${dialplan_exts}"
for i in ${dialplan_exts} ; do
eval "local curext=\"\${dialplan_ext_$i}\""
add_dialplan_exten extensions $i $curext
done
}
append_include() {
append dialplan_includes "#include <$1>" "$N"
}
create_dialplanconf() {
# Add general section
logdebug 1 "Dialplan: Add general section"
local file=${DEST_DIR}/extensions.conf
get_checksum dialplan_conf $file
echo "${asteriskuci_gen}" > $file
[ -z "${dialplan_includes}" ] || (echo "${dialplan_includes}${N}" >> $file)
if [ ! -z "${dialplan_globals}" ] ; then
echo "[globals]${N}${dialplan_globals}${N}" >> $file
fi
echo "[general]" >> $file
for i in ${dialplangeneral_list} ; do
eval "local val=\"\$dialplan_$i\""
if [ ! -z "$val" ] ; then
echo "$i=$val" >> $file
fi
done
append_dialplan_dialzone "$file"
append_dialplan_dialzone_out "$file"
append_dialplan_park "$file"
append_dialplan_extensions "$file"
append_dialplan_incoming "$file"
# append_dialplan_lastcall "$file"
# Add all the contexts
logdebug 1 "Dialplan: Add all the contexts"
for i in ${dialplan_contexts} ; do
echo "${N}[$i]" >> $file
[ "${i#macro-}" == "${i}" ] || i=macro__${i#macro-}
eval "local curcontext=\"\${dialplan_context_$i-}\""
echo "$curcontext">> $file
eval unset dialplan_context_$i
done
check_checksum "$dialplan_conf" "$file" || ast_dialplan_restart=1
return 0
}
handle_dialplangeneral() {
option_cb(){
if valid_dialplangeneral $1 $2 ; then
eval "dialplan_$1=\"$2\""
else
logerror "Invalid Dialplan General option: $1"
fi
}
}
handle_dialplan(){
context_name=$1
if [ -z ${context_name} ] ; then
logerror "Context name required for dialplan"
context_name=default
fi
option_cb() {
logdebug 4 "dialplan ${context_name}: '$1' '$2'"
case $1 in
include_LENGTH) ;;
include|include_ITEM*) add_dialplan_include ${context_name} $2 ;;
*)
lhs=$1
logdebug 4 "Add extension $lhs"
if [ "$(expr $lhs : [0-9][0-9]\*)" != 0 ] ; then
addtype=${2%%:*}
if [ "${addtype}" == "$2" ]; then
addparam=
else
addparam=${2#*:}
fi
case ${addtype} in
mailbox|voice)
add_dialplan_voice ${context_name} $1 $addparam ;;
meetme|conf|conference) add_dialplan_meetme ${context_name} $1 $addparam ;;
saytime|time) add_dialplan_saytime ${context_name} $1 $addparam ;;
clock) add_dialplan_talkclock ${context_name} $1 $addparam ;;
*) logerror "Unknown type '${addtype}' in dialplan ${context_name}, extension ${1}"
esac
else
logerror "Invalid option: $1 for dialplan ${context_name}"
fi
esac
}
}
handle_dialplanexten() {
check_add dialplanexten
option_cb() {
case $1 in
dialplan|extension|type|target|dialextension|voicebox|timeout|answerfirst)
eval "dial_exten_$1=\"$2\""
esac
}
}
check_add_dialplanexten() {
if [ ! -z "${dial_exten_dialplan}" -a ! -z "${dial_exten_extension}" ] ; then
local dialtarget=${dial_exten_type}/${dial_exten_dialextension+@}${dial_exten_dialextension}${dial_exten_target}
check_add_context ${dial_exten_dialplan}
add_dialplan_exten "${dial_exten_dialplan}" "${dial_exten_extension}" \
"${dialtarget}" "${dial_exten_voicebox}" "${dial_exten_timeout}" \
"${dial_exten_answerfirst}"
fi
for i in dialplan extension voicebox type target dialextension timeout answerfirst ; do
eval "unset dial_voice_$i"
done
}
handle_dialplansaytime() {
check_add dialplansaytime
option_cb() {
case $1 in
dialplan|extension|zone|format)
eval "dial_saytime_$1=\"$2\""
esac
}
}
check_add_dialplansaytime() {
logdebug 1 "Add Saytime to $1 / $2"
if [ ! -z "${dial_saytime_dialplan}" -a ! -z "${dial_saytime_extension}" ] ; then
# local ext="exten => ${dial_saytime_extension},"
[ -z "${dial_saytime_dialplan}" ] && dial_saytime_dialplan=default
add_dialplan_saytime "${dial_saytime_dialplan}" "${dial_saytime_extension}" \
"${dial_saytime_zone}" "${dial_saytime_format}"
fi
for i in dialplan extension zone format; do
eval "unset dial_saytime_$i"
done
}
handle_dialzone_match() {
eval "local isadded=\"\${dzone_${zone_name}-0}\""
if [ "${isadded}" != "1" ] ; then
eval "dzone_${zone_name}=1"
append dzones_match ${zone_name} " "
fi
append dzone_${zone_name}_match $1 ","
}
# Set up outgoing zones (match patterns)
handle_dialzone() {
zone_name=$1
logdebug 2 "Loading dialzone: $zone_name"
option_cb(){
logdebug 2 "Dialzone $1/$2"
case $1 in
uses)
local areatype=${2%[-/]*}
local areaname=${2#*[-/]}
logdebug 3 "Added: $areatype $areaname"
eval "local isadded=\"\${dzone_${areatype}_${areaname}-0}\""
if [ "${isadded}" != "1" ] ; then
eval dzone_${areatype}_${areaname}=1
append dzones_${areatype} "${areaname}" " "
fi
eval "dzone_match_use_${zone_name}=${areatype}_${areaname}"
logdebug 3 "Finished uses"
;;
match_LENGTH) ;;
match|match_ITEM*)
handle_dialzone_match "$2"
;;
international_LENGTH) ;;
international|international_ITEM*)
eval "local isadded=\"$dzone_${zone_name}\""
if [ "${isadded}" != "1" ] ; then
eval "dzone_${zone_name}=1"
append dzones_match ${zone_name} " "
fi
append dzone_${zone_name}_international $2 ","
;;
countrycode|localzone|addprefix|localprefix)
eval "dzone_${zone_name}_${1}=\"$2\""
eval "y=\${dzone_${zone_name}_${1}}"
;;
*)
logerror "Invalid Dialzone option: $1 in zone '${zone_name}'" ;;
esac
}
}
check_add_dialplangoto() {
logdebug 1 "Add Goto to $1 / $2"
if [ ! -z "${dial_goto_dialplan}" -a ! -z "${dial_goto_extension}" ] ; then
local ext="exten => ${dial_goto_extension},"
check_add_context ${dial_goto_dialplan}
append_dialplan_context ${dial_goto_dialplan} "${ext}1,Goto(${dial_goto_target})"
fi
for i in dialplan extension room ; do
eval "unset dial_goto_$i"
done
}
handle_dialplangoto(){
check_add dialplangoto
option_cb() {
case $1 in
dialplan|extension|target)
eval "dial_goto_$1=\"$2\"" ;;
*) logerror "Invalid dialplangoto option: $1"
esac
}
}
# Options for incoming calls.
valid_incoming_list="allowtransfer timeout answerfirst mailbox lastcall lastcalltype missed missedtype"
valid_incoming_option() {
is_in_list $1 ${valid_incoming_list}
return $?
}
handle_incominggeneral() {
option_cb() {
if valid_incoming_option $1 ; then
logdebug 3 "Add Incoming General option $1=$2"
eval "incoming_${1}=\"$2\""
else
logerror "Invalid incominggeneral option $1"
fi
}
}
handle_incoming() {
incoming_context=$1
incoming_list=
add_incoming_context "${incoming_context}"
option_cb() {
logdebug 1 "Incoming ${incoming_context} $1=$2"
case $1 in
lastcall|lastcalltype|missed|missedtype) eval "incoming_${incoming_context}_${1}=\"$2\"" ;;
# lastcall|lastcallexten|lastmissed|lastmissedexten)
# enable_lastcall
# eval "incoming_${incoming_context}_${1}=\"$2\""
# ;;
mailbox|allowtransfer|answerfirst|beforeanswer|timeout|menucontext|match|matchcaller|aftertimeout|aftertimeouttype)
eval "incoming_${incoming_context}_${1}=\"$2\""
;;
target|target_ITEM*)
append dialplan_incoming_${incoming_context} "$2" "&"
;;
target_COUNT) ;;
*) logerror "Invalid option $1 in incoming" ;;
esac
}
}
# vim: ts=2 sw=2 noet foldmethod=indent

View file

@ -0,0 +1,84 @@
dialplangeneral
asterisk options:
static
writeprotect
canreinvite
clearglobalvars
global settings for dialzone out:
lastdialed
lastdialedtype
Global option for dialplanexten:
answerfirst
dialtimeout
allowtransfer - allow transfers in dialing
voiceboxext Extension to use for voicebox set on local client
international
internationalout
dialplan {name} - Define a dialplan context
include
#=mailbox|voice|meetme|saytime|clock
dialplanexten - Add number to Dialplan for ringing an extension
dialplan - Dialplan to add to
extension - Number to dial
type - Channel type sip/iax/local
target - Target
dialextension - Extension to dial
voicebox - Voicebox to fall back to
timeout - Timeout for dial
answerfirst - Answer before dialing
dialplangoto
dialplan|extension|target)
dialplansaytime
dialplan - Dialplan to add to
extension - Number to dial
zone - Time Zone to use
format - Format to use.
dialzone {name} - Outgoing zone.
uses - Outgoing line to use: TYPE/Name
match (list) - Number to match
countrycode - The effective country code of this dialzone
international (list) - International prefix to match
localzone - dialzone for local numbers
addprefix - Prexix required to dial out.
localprefix - Prefix for a local call
inzone
TODO
incominggeneral
allowtransfer - Default Allow transfers for Dial()
timeout - Default timeout for incoming calls
answerfirst - Default value for incoming calls
mailbox - Default global mailbox for incoming calls
lastcall - Subroutine Context to store Last incoming call
lastcalltype - Method for calling lastcall (default goto) goto|gosub|macro|start
missed - Subroutine context to store last missed call dialplan context
missedtype - Method for calling 'missed' context goto|gosub|macro|start
incoming {name} - Incoming zone
allowtransfer - Allow transfers for Dialed extension
timeout - Timeout for call
answerfirst - Answer the incoming call before Ringing
mailbox - Voicemail mailbox to use when
beforeanswer - Time to ring before asterisk 'answers' and takes control of the call
menucontext - EXITCONTEXT for the ring once asterisk is handling the call
match - Dialed number to match
matchcaller - Caller to match
aftertimeout - Target macro/goto once the timeout has past, before voicemail
aftertimeouttype - Type of the target (macro|start|goto)
lastcall - Subroutine Context to store Last incoming call
lastcalltype - Method for calling lastcall (default goto) goto|gosub|macro|start
missed - Subroutine context to store last missed call dialplan context
missedtype - Method for calling 'missed' context goto|gosub|macro|start

View file

@ -0,0 +1,99 @@
#!/bin/sh
# Feature.conf
ast_add_conf feature
init_featureconf(){
ast_add_reload feature
ast_enable_type feature
ast_enable_type featurepark
ast_enable_type featuremap
feature_park_parkenabled=no
feature_park_parkext=700
feature_park_parkpos="701-720"
feature_park_context=parkedcalls
feature_park_parkingtime=45
feature_park_courtesytone=beep
feature_park_parkedplay=caller
feature_park_adsipark=yes
feature_park_findslot=first
feature_park_parkedmusicclass=default
feature_park_transferdigittimeout=3
feature_park_xfersound=beep
feature_park_xferfailsound=beeperr
feature_park_pickupexten="*8"
feature_park_featuredigittimeout=500
feature_park_atxfernoanswertimeout=15
}
feature_park_list="parkext parkpos context parkingtime \
courtesytone parkedplay adsipark findslot parkedmusicclass \
transferdigittimeout xfersound xferfailsound pickupexten \
featuredigittimeout atxfernoanswertimeout"
feature_map_list="blindxfer disconnect automon atxfer parkcall"
valid_features(){
case $1 in
park) is_in_list $2 ${feature_park_list} parkenabled ; return $? ;;
map) is_in_list $2 ${feature_map_list} ; return $? ;;
*) return 1;;
esac
}
create_featureconf(){
file=${DEST_DIR}/features.conf
get_checksum feature_conf $file
local isempty=1
if [ $feature_park_parkenabled == no ] ; then
rm -f $file
isempty=2
else
enable_module res_features
echo "${asteriskuci_gen}${N}[general]" > $file
for i in ${feature_park_list} ; do
eval value="\"\${feature_park_$i}\""
[ ! -z "$value" ] && echo "$i=$value" >> $file
done
echo "${N}[featuremap]" >> $file
for i in ${feature_map_list} ; do
eval value="\"\${feature_map_$i}\""
[ ! -z "$value" ] && echo "$i=$value" >> $file
done
fi
check_checksum "$feature_conf" "$file" || ast_feature_restart=$isempty
}
handle_featurepark() {
handle_feature park
}
handle_featuremap() {
handle_feature map
}
handle_feature() {
feature_type=$1
option_cb() {
if valid_features ${feature_type} $1 $2 ; then
eval "feature_${feature_type}_$1=\"$2\""
else
logerror "Invalid feature: $1"
fi
}
}
append_dialplan_park(){
local file=$1
# Check for parked calls - add into available extensions
if [ ${feature_park_parkenabled} == yes ] && [ ! -z ${feature_park_context} ] ; then
add_dialplan_include extensions ${feature_park_context}
enable_module app_parkandannounce
enable_format gsm
fi
}
reload_feature() astcmd "module reload res_features.so"
unload_feature() astcmd "module unload res_features.so"
# vim: ts=2 sw=2 noet foldmethod=indent

View file

@ -0,0 +1,25 @@
See asterisk doco
featurepark
parkext
parkpos
context
parkingtime
courtesytone
parkedplay
adsipark
findslot
parkedmusicclass
transferdigittimeout
xfersound
xferfailsound
pickupexten
featuredigittimeout
atxfernoanswertimeout
featuremap
blindxfer
disconnect
automon
atxfer
parkcall

View file

@ -0,0 +1,119 @@
#!/bin/sh
#
# Author: Michael Geddes <michael at frog dot wheelycreek dot net>
# Copyright 2008 Michael Geddes
# Licensed under GPL
ast_add_module lastcall
init_lastcall() {
#
ast_enable_type calllist
ast_enable_type calllistdefault
}
check_add_calllist() {
local context=${opt_calllist_zonename}
if [ ! -z "$context" ] ; then
logdebug 1 "Adding calllist context ${context}"
[ -z $opt_calllist_dialplan ] && opt_calllist_dialplan=${opt_calllist_general_dialplan}
[ -z $opt_calllist_dialplan ] && opt_calllist_dialplan=extensions
[ -z $opt_calllist_listname ] && opt_calllist_listname=lastcall
[ -z $opt_calllist_length ] && opt_calllist_length=${opt_calllist_general_length}
[ -z $opt_calllist_length ] && opt_calllist_length=10
[ -z $opt_calllist_dialcontext ] && opt_calllist_dialcontext=${opt_calllist_general_dialcontext}
[ -z $opt_calllist_dialcontext ] && opt_calllist_dialcontext=default
[ -z $opt_calllist_calltype ] && opt_calllist_calltype=macro
[ -z ${opt_calllist_extension} ] \
|| add_dialplan_lastcall ${opt_calllist_dialplan} "${opt_calllist_extension}" "${opt_calllist_listname}" "${opt_calllist_length}" "${opt_calllist_tagname}" "${opt_calllist_dialcontext}"
enable_lastcall
add_section_lastcall ${context} "${opt_calllist_listname}" "${opt_calllist_length}" "${opt_calllist_calltype}"
fi
for i in zonename extension dialplan length listname ; do
eval "unset opt_calllist_${i}"
done
}
add_section_lastcall() {
local context=$1
local name=$2
local queuelen=$3
local calltype=$4
[ "${calltype}" = "macro" ] && context=macro-${1}
if check_add_context ${context} ; then
local ext="exten => s,"
case "${calltype}" in
gosub)
enable_module app_stack
append_dialplan_context ${context} "${ext}1,Macro(lastcallstore,\${EXTEN},${name},${queuelen})"
append_dialplan_context ${context} "${ext}n,Return" ;;
gosub_s)
enable_module app_stack
append_dialplan_context ${context} "${ext}1,Macro(lastcallstore,\${ARG1},${name},${queuelen})"
append_dialplan_context ${context} "${ext}n,Return" ;;
macro)
enable_module app_macro
append_dialplan_context ${context} "${ext}1,Macro(lastcallstore,\${ARG1},${name},${queuelen})" ;;
esac
else
logerror "Lastcall section ${context} already added"
fi
}
handle_calllist() {
check_add calllist
logdebug 2 "Loading Call List: ${opt_calllist_zonename}"
opt_calllist_zonename=$1
option_cb() {
case "$1" in
extension|dialplan|length|listname|calllist|tagname|dialcontext|calltype)
logdebug 1 "Setting opt_calllist_$1=\"${2}\""
eval "opt_calllist_${1}=\"${2}\"" ;;
*)
logerror "Unknown option $1 in calllist ${opt_calllist_zonename}" ;;
esac
}
}
handle_calllistdefault() {
logdebug 2 "Loading Call List General options"
option_cb() {
case $1 in
dialplan|length|dialcontext)
eval "opt_calllist_general_${1}=\"${2}\"" ;;
*) logerror "Unknown option $1 in calllistdefault" ;;
esac
}
}
add_dialplan_lastcall(){
local context=$1
logdebug 1 "Adding Dialplan lastcall $1 $2"
check_add_context "$context"
enable_lastcall
local queue=$3
local len=$4
local tag=$5
local dialcontext=$6
[ "${queue}" == lastcall ] && queue=
append dialplan_context_${context} "exten => $2,1,Macro(lastcallapp,${queue},${len},${dialcontext},${tag})" "${N}"
}
enable_lastcall() {
if [ "${dialplan_do_add_lastcall}" != "1" ] ; then
logdebug 2 "Enabling lastcall"
append dialplan_globals "LASTCALLZONE=\"${asterisk_zone}\"" "$N"
append_include "macros/lastcall.conf"
dialplan_do_add_lastcall=1
enable_module app_macro
enable_module func_callerid
enable_module app_sayunixtime
enable_module app_playback
enable_module func_db
enable_format gsm
fi
}
# vim: ts=2 sw=2 noet foldmethod=indent

View file

@ -0,0 +1,15 @@
calllistdefault
dialplan - Override default dialplan for calllist extensions to be added to.
length - Default Length of list
dialcontext - Default Context for dialing
calllist {name} - Define a call list context
extension - Extension to review list
dialplan - Dialplan for extension to be added to (default to extensions)
length - Length of list
listname - Name of list to use
tagname - Sound file to use for name
dialcontext - Context to use when dialing
calltype - Type of context for the wrapper (required when calling it) macro|gosub

View file

@ -0,0 +1,107 @@
#!/bin/sh
# Meetme.conf (conference)
ast_add_conf meetme
init_meetmeconf() {
ast_add_reload meetme
ast_enable_type meetmegeneral
ast_enable_type meetme
ast_enable_type dialplanmeetme
}
create_meetmeconf() {
file=${DEST_DIR}/meetme.conf
get_checksum meetme_conf $file
logdebug 1 "Creating meetme rooms: ${meetme_rooms}"
local isempty=1
if [ -z ${meetme_rooms} ] ; then
rm -f $file
isempty=2
else
echo "${asteriskuci_gen}${N}[general]" > $file
if [ ! -z ${meetme_audiobuffers} ] ; then
echo "audiobuffers=${meetme_audiobuffers}" >> $file
fi
echo "${N}[rooms]" >> $file
for i in ${meetme_rooms} ; do
for j in pin adminpin room ; do
eval meetme_$j=\${meetme_room_${i}_${j}}
done
if [ -z "${meetme_room}" ] ; then
meetme_room=$i
fi
local line="conf => ${meetme_room}"
if [ -z ${meetme_adminpin} ] ; then
if [ ! -z ${meetme_pin} ] ; then
line="${line},${meetme_pin}"
fi
else
line="${line},${meetme_pin},${meetme_adminpin}"
fi
echo "$line" >> $file
done
fi
check_checksum "$meetme_conf" "$file" || ast_meetme_restart=$isempty
}
handle_meetmegeneral() {
option_cb() {
case $1 in
audiobuffers)
meetme_audiobuffers="$2" ;;
*) logerror "Invalid meetme general option $1"
esac
}
}
handle_meetme() {
logdebug 2 "Add meetme room $1"
meetme_room="$1"
append meetme_rooms "$1" " "
enable_module app_meetme
option_cb() {
case $1 in
pin|adminpin|room)
logdebug 3 "Meetme option ${meetme_room}/${1}=$2"
eval meetme_room_${meetme_room}_${1}="$2" ;;
*) logerror "Invalid meetme option for $meetme_room : $1"
esac
}
}
handle_dialplanmeetme() {
check_add dialplanmeetme
option_cb() {
case $1 in
dialplan|extension|room)
eval "dial_meetme_$1=\"$2\""
esac
}
}
check_add_dialplanmeetme() {
if [ ! -z "${dial_meetme_extension}" ] ; then
local ext="exten => ${dial_meetme_extension},"
[ -z "${dial_meetme_dialplan}" ] && dial_meetme_dialplan=extensions
check_add_context ${dial_meetme_dialplan}
append dialplan_context_${dial_meetme_dialplan} "${ext}1,MeetMe(${dial_meetme_room})" "${N}"
append dialplan_context_${dial_meetme_dialplan} "${ext}n,HangUp" "${N}"
fi
for i in dialplan extension room ; do
eval "unset dial_meetme_$i"
done
}
add_dialplan_meetme() {
local context=$1
logdebug 1 "Adding Dialplan meetme $1 $2"
check_add_context "$context"
local ext="exten => $2,"
append dialplan_context_${context} "${ext}1,MeetMe($3)" "${N}"
append dialplan_context_${context} "${ext}n,HangUp" "${N}"
}
reload_meetme() astcmd "module reload app_meetme.so"
unload_meetme() astcmd "module unload app_meetme.so"
# vim: ts=2 sw=2 noet foldmethod=indent

View file

@ -0,0 +1,13 @@
meetmegeneral
audiobuffers
meetme - add a meetme room
room - Number of room
pin - PIN for room
adminpin - PIN for room admin
dialplanmeetme - add calling of meetme to a dialplan
dialplan - Dialplan to add to (default 'extensions')
extension - Extension to dial
room - Optional room to enter

View file

@ -0,0 +1,151 @@
#!/bin/sh
# Module.conf
init_moduleconf() {
ast_add_reload module
ast_enable_type module
for i in ${module_list} ; do
eval module_${i}=no
done
enable_module app_dial
enable_module app_read
enable_module app_verbose
enable_module pbx_config
enable_module pbx_functions
enable_module app_transfer
module_chan_local=auto
# Sound files are all gsm
enable_format gsm
enable_module app_func_strings
}
# List of modules in sensible load order.
module_list="res_agi res_adsi res_config_mysql res_crypto res_smdi res_features \
res_indications res_convert res_jabber res_monitor res_musiconhold res_speech \
res_clioriginate pbx_ael pbx_config pbx_functions pbx_loopback pbx_realtime \
pbx_spool pbx_wilcalu func_base64 func_callerid func_cdr func_channel func_cut \
func_db func_enum func_env func_global func_groupcount func_language func_logic \
func_moh func_rand func_realtime func_sha1 func_strings func_timeout func_uri \
cdr_csv cdr_custom cdr_manager cdr_mysql cdr_pgsql cdr_sqlite chan_agent \
chan_alsa chan_gtalk chan_h323 chan_iax2 chan_local chan_sip format_au \
format_g723 format_g726 format_g729 format_gsm format_h263 format_h264 \
format_ilbc format_jpeg format_mp3 format_pcm format_pcm_alaw format_sln \
format_vox format_wav format_wav_gsm app_alarmreceiver app_amd app_authenticate \
app_cdr app_chanisavail app_channelredirect app_chanspy app_controlplayback \
app_cut app_db app_dial app_dictate app_directed_pickup app_directory app_disa \
app_dumpchan app_echo app_enumlookup app_eval app_exec app_externalivr \
app_followme app_forkcdr app_getcpeid app_groupcount app_hasnewvoicemail \
app_ices app_image app_lookupblacklist app_lookupcidname app_macro app_math \
app_md5 app_meetme app_milliwatt app_mixmonitor app_morsecode \
app_parkandannounce app_playback app_privacy app_queue app_random app_read \
app_readfile app_realtime app_record app_sayunixtime app_senddtmf app_sendtext \
app_setcallerid app_setcdruserfield app_setcidname app_setcidnum app_setrdnis \
app_settransfercapability app_sms app_softhangup app_speech_utils app_stack \
app_system app_talkdetect app_test app_transfer app_txtcidname app_url \
app_userevent app_verbose app_voicemail app_waitforring app_waitforsilence \
app_while codec_a_mu codec_adpcm codec_alaw codec_g726 codec_gsm codec_ilbc \
codec_lpc10 codec_speex codec_ulaw"
# Enable a module - for use by other scripts
enable_module() {
logdebug 3 "Enable ${1}"
eval module_${1}=yes
}
module_enabled() {
eval local is_enabled="\${module_${1}}"
if [ ${is_enabled} == "no" ] ; then
return 1
else
return 0
fi
}
# Enable a sound format - for use by other scripts
enable_format() {
while [ ! -z $1 ] ; do
case $1 in
gsm)
enable_module format_gsm
enable_module codec_gsm
[ "${module_format_wav}" = "yes" ] && enable_module format_wav_gsm ;;
wav)
enable_module format_wav
[ "${module_format_gsm}" = "yes" ] && enable_module format_wav_gsm ;;
alaw)
enable_module codec_adpcm
enable_module codec_alaw
[ "${module_format_pcm}" = "yes" ] && enable_module format_pcm_alaw ;;
pcm)
enable_module format_pcm_alaw
[ "${module_format_alaw}" = "yes" ] && enable_module format_pcm_alaw ;;
ulaw)
enable_module codec_ulaw ;;
g729|g726|g723)
enable_module format_g726
enable_module codec_g726 ;;
ilbc)
enable_module format_ilbc
enable_module codec_ilbc ;;
sln) enable_module format_sln ;;
mp3) enable_module format_mp3 ;;
vox) enable_module format_vox ;;
speex) enable_module codec_speex ;;
esac
shift
done
}
create_moduleconf() {
local file=${DEST_DIR}/modules.conf
get_checksum module_conf $file
rm -f ${file}.orig
[ -f "${file}" ] && mv ${file} ${file}.orig
echo "${asteriskuci_gen}[modules]${N}autoload=yes" > $file
for i in ${module_list} ; do
eval res=\${module_${i}}
case $res in
yes) echo "load => $i.so" >> $file ;;
no) echo "noload => $i.so" >> $file ;;
esac
done
echo "${N}[global]${N}chan_modem.so=no" >> $file
check_checksum "$module_conf" "$file" || ast_module_restart=1
}
reload_module() {
local file=${DEST_DIR}/modules.conf
local cmd=`diff ${file}.orig ${file} -u -U0 | grep '^+\(no\)\?load' | sed 's/+load[[:space:]]*=>[[:space:]]*\(.*\)$/\"module load \1\"/' | sed 's/+noload[[:space:]]*=>[[:space:]]*\(.*\)$/\"module unload \1\"/'| tr '\n' ' '`
[ "${testing_mode}" != "1" ] && rm -f ${file}.orig
logdebug 3 "Module reload: ${N}$cmd"
eval "astcmds $cmd"
}
valid_module() {
is_in_list $1 ${module_list}
return $?
}
handle_module() {
option_cb() {
if valid_module $1 ; then
eval module_$1="$2"
else
logerror "Invalid module: $1"
fi
}
}
# vim: ts=2 sw=2 noet foldmethod=indent

View file

@ -0,0 +1,151 @@
module - Enable modules (yes/no/auto)
res_agi
res_adsi
res_config_mysql
res_crypto
res_smdi
res_features
res_indications
res_convert
res_jabber
res_monitor
res_musiconhold
res_speech
res_clioriginate
pbx_ael
pbx_config
pbx_functions
pbx_loopback
pbx_realtime
pbx_spool
pbx_wilcalu
func_base64
func_callerid
func_cdr
func_channel
func_cut
func_db
func_enum
func_env
func_global
func_groupcount
func_language
func_logic
func_moh
func_rand
func_realtime
func_sha1
func_strings
func_timeout
func_uri
cdr_csv
cdr_custom
cdr_manager
cdr_mysql
cdr_pgsql
cdr_sqlite
chan_agent
chan_alsa
chan_gtalk
chan_h323
chan_iax2
chan_local
chan_sip
format_au
format_g723
format_g726
format_g729
format_gsm
format_h263
format_h264
format_ilbc
format_jpeg
format_mp3
format_pcm
format_pcm_alaw
format_sln
format_vox
format_wav
format_wav_gsm
app_alarmreceiver
app_amd
app_authenticate
app_cdr
app_chanisavail
app_channelredirect
app_chanspy
app_controlplayback
app_cut
app_db
app_dial
app_dictate
app_directed_pickup
app_directory
app_disa
app_dumpchan
app_echo
app_enumlookup
app_eval
app_exec
app_externalivr
app_followme
app_forkcdr
app_getcpeid
app_groupcount
app_hasnewvoicemail
app_ices
app_image
app_lookupblacklist
app_lookupcidname
app_macro
app_math
app_md5
app_meetme
app_milliwatt
app_mixmonitor
app_morsecode
app_parkandannounce
app_playback
app_privacy
app_queue
app_random
app_read
app_readfile
app_realtime
app_record
app_sayunixtime
app_senddtmf
app_sendtext
app_setcallerid
app_setcdruserfield
app_setcidname
app_setcidnum
app_setrdnis
app_settransfercapability
app_sms
app_softhangup
app_speech_utils
app_stack
app_system
app_talkdetect
app_test
app_transfer
app_txtcidname
app_url
app_userevent
app_verbose
app_voicemail
app_waitforring
app_waitforsilence
app_while
codec_a_mu
codec_adpcm
codec_alaw
codec_g726
codec_gsm
codec_ilbc
codec_lpc10
codec_speex
codec_ulaw

View file

@ -0,0 +1,74 @@
#!/bin/sh
# Music on Hold
ast_add_conf moh
init_mohconf() {
ast_add_reload moh
ast_enable_type moh
ast_enable_type musiconhold
}
handle_musiconhold() handle_moh "$1"
moh_list="name"
moh_optlist="mode directory random application format"
valid_moh() {
is_in_list $1 ${moh_list} ${moh_optlist}
return $?
}
handle_moh() {
check_add moh
moh_context=$1
logdebug 1 "Loading MOH context: ${moh_context}"
enable_module res_musiconhold
option_cb() {
if valid_moh $1 $2 ; then
eval "moh_var_${1}=\"$2\""
else
logerror "Invalid music-on-hold option for ${moh_context} : $1"
fi
}
}
check_add_moh() {
if [ ! -z "${moh_var_directory}" ] ; then
[ -z "${moh_var_name}" ] && moh_var_name=default
[ -z "${moh_var_mode}" ] && moh_var_mode=files
append moh_lines "[${moh_var_name}]" "${N}${N}"
for i in ${moh_optlist} ; do
eval "local curopt=\"\${moh_var_$i}\""
[ -z "${curopt}" ] || append moh_lines "$i=${curopt}" "${N}"
done
fi
for i in ${moh_list} ${moh_optlist} ; do
eval "unset moh_var_$i"
done
}
create_mohconf() {
file=${DEST_DIR}/musiconhold.conf
get_checksum moh_conf $file
local isempty=1
if [ -z "${moh_lines}" ] ; then
isempty=2
rm -f $file
else
echo "${asteriskuci_gen}" > $file
echo "${moh_lines}" >> $file
unset moh_lines
fi
check_checksum "$moh_conf" "$file" || ast_moh_restart=$isempty
}
reload_moh() astcmd "moh reload"
unload_moh() astcmd "module unload res_musiconhold.so"
# vim: ts=2 sw=2 noet foldmethod=indent

View file

@ -0,0 +1,8 @@
musiconhold/moh - Musicon-on-hold context
name - MOH context name
mode - Playback mode (files)
directory - Directory of music
random - Playback is random
application - Application to use
format - file format of files

View file

@ -0,0 +1,545 @@
#!/bin/sh
# Sip / IAX extensions
add_incoming_context() {
local context=$1
eval "local added=\${dialplan_incoming_${context}_added}"
if [ "${added}" != "1" ] ; then
append dialplan_extensions_incoming "${context}" " "
eval "dialplan_incoming_${context}_added=1"
fi
}
# Add to incoming ringing
add_incoming() {
local rhs="$3"
while [ ! -z "$rhs" ] ; do
cur=${rhs%%,*}
nvar=${rhs#*,}
add_incoming_context ${cur}
append dialplan_incoming_${cur} "$1/$2" "&"
[ "$nvar" == "$rhs" ] && break
rhs=${nvar}
done
}
# Add to internal extensions
add_extension() {
logdebug 1 "Adding $1/$2 extension to $3"
(eval [ -z "\${dialplan_ext_$2}" ] )\
&& append dialplan_exts "$3" " "
local lower=`echo $1|tr [A-Z] [a-z]`
eval "${lower}_last_extension=\"$3\""
append dialplan_ext_$3 $1/${2} "&"
}
check_append_local() {
local extension="${1}"
logdebug 3 "added local context for ${1}"
eval "local isadded=\"\${dialplan_add_local_${extension}-0}\""
if [ "$isadded" != "1" ] ; then
eval "dialplan_add_local_${extension}=1"
append dialplan_locals "$extension"
eval "dialplan_local_${1}_context=\"${2}\""
eval "dialplan_local_${1}_selfmailbox=\"${3}\""
eval "dialplan_local_${1}_mailbox=\"${4}\""
return 0
else
return 1
fi
}
append_dialplan_locals(){
for i in ${dialplan_locals} ; do
local extension=$i
for x in context selfmailbox mailbox ; do
eval "x_${x}=\${dialplan_local_${i}_${x}}"
done
local newcontext=local_${extension}
if check_add_context ${newcontext} ; then
# add_dialplan_voice ${newcontext} ${x_last_extension} ${x_last_mailbox}
# Make sure as much is matched as possible
#add_dialplan_goto ${newcontext} _[0-9#*+]. ${x_last_context}
# add_dialplan_include ${newcontext} ${x_last_context}
append_dialplan_context ${newcontext} "exten => _.,1,Set(CALLERID(num)=${extension})"
if [ ! -z "${x_mailbox}" ] ; then
[ "${x_selfmailbox}" = "yes" ] && append_dialplan_context ${newcontext} "exten => ${extension},2,VoiceMailMain(${x_mailbox})"
[ ! -z "${dialplan_voiceboxext}" ] && append_dialplan_context ${newcontext} "exten => ${dialplan_voiceboxext},2,VoiceMailMain(${x_mailbox})"
fi
append_dialplan_context ${newcontext} "exten => _.,2,Goto(${x_context},\${EXTEN},1)"
fi
done
}
# Sip
check_add_sipitems() {
if [ "${sip_doregister}" == "1" ] ; then
local line="register => ${sip_last_username}@${sip_last_fromdomain}:${sip_last_secret}:${sip_last_username}@${sip_sectionname}"
case ${sip_last_registerextension} in
-) line="$line/${sip_last_username}" ;;
.*) line="$line/${sip_last_registerextension}" ;;
esac
append sip_register "$line" "$N"
sip_doregister=0
fi
do_check_add_items sip
}
check_add_iaxitems() {
do_check_add_items iax
}
do_check_add_items(){
for i in type last_host last_context selfmailbox last_extension last_mailbox ; do
eval "x_${i}=\"\${${1}_${i}-}\""
done
if [ ! -z "${x_last_context}" ] ; then
if [ ! -z "${x_last_extension}" ] ; then
[ "${x_last_context}" = "-" ] && eval "x_last_context=\"\${${1}_opt_context}\""
check_append_local "${x_last_extension}" "${x_last_context}" "${x_selfmailbox}" "${x_last_mailbox}"
x_last_context=local_${x_last_extension}
fi
if [ "${x_last_context}" != "-" ] ; then
append ${1}_sections "context=${x_last_context}" "$N"
fi
if [ "${x_type}" != "user" -a -z "${x_last_host}" ] ; then
append ${1}_sections "host=dynamic" "$N"
fi
fi
for i in last_username last_fromdomain last_secret last_username \
sectionname last_fromuser last_context last_extension last_mailbox last_type last_host ; do
eval unset $1_$i
done
eval ${1}_selfmailbox=no
eval ${1}_last_registerextension=-
}
reload_sip() {
astcmd "sip reload"
return 1 # reboot
}
unload_sip() astcmd "unload chan_sip.so"
rtp_option_list="rtpstart rtpend rtpdtmftimeout rtcpinterval rtpchecksums"
# Validate RTP options
valid_rtp_option() {
is_in_list $1 ${rtp_option_list}
}
# Validate sip options, depending on context.
valid_sipiax_option() {
local use_glob=1
local use_glob_iax=1
local use_glob_sip=1
local use_user=1
local use_peer=1
local use_user_sip=1
local use_user_iax=1
local use_peer_sip=1
local use_peer_iax=1
case "$1" in
globalsip)
use_glob_sip=0
use_glob=0 ;;
usersip)
use_glob_sip=0
use_glob=0
use_user=0 ;;
peersip|friendsip)
use_glob_sip=0
use_glob=0
use_user=0
use_peer=0
use_user_sip=0
use_peer_sip=0 ;;
globaliax)
use_glob_iax=0
use_glob=0 ;;
useriax)
use_glob_iax=0
use_glob=0
use_user=0 ;;
peeriax|friendiax)
use_glob_iax=0
use_glob=0
use_user=0
use_peer=0
use_user_iax=0
use_peer_iax=0 ;;
esac
case "$2" in
writeprotect|static) return ${use_glob_iax} ;;
# Integer
port|\
maxexpirey|\
rtptimeout|\
rtpholdtimeout|\
defaultexpirey|\
registertimeout|\
registerattempts|\
call-limit) return ${use_glob_sip} ;;
# ip addr
bindaddr|\
externip) return ${use_glob_sip} ;;
# net/mask
localnet) return ${use_glob_sip} ;;
permit|\
deny) return ${use_user_sip} ;;
# Domain name
realm|\
domain) return ${use_glob_sip} ;;
# valid context
context) return ${use_glob} ;;
# Mime type
notifymimetype) return ${use_glob_sip} ;;
# Yes/No
canreinvite) return ${use_glob} ;;
nat|allowoverlap|allowsubscribe|allowtransfer|\
videosupport) return ${use_glob_sip} ;;
pedantic|\
trustrpid|\
promiscredir|\
useclientcode) return ${use_user_sip} ;;
# Enums
dtmfmode) return ${use_glob_sip} ;;
type) return ${use_user} ;;
insecure|callingpres|\
progressinband) return ${use_user_sip} ;;
# List
allow|\
disallow) return ${use_glob_sip} ;;
# Register string
register) return ${use_glob_sip} ;;
# String
username|secret|md5secret|host|\
mailbox) return ${use_user} ;;
auth) return ${use_user_iax} ;;
callgroup|pickupgroup|language|accountcode|\
setvar|callerid|amaflags|subscribecontext|\
maxcallbitrate|rfc2833compensate|\
mailbox) return ${use_user_sip};;
template|fromdomain|regexten|fromuser|\
qualify|defaultip|sendrpid|\
outboundproxy) return ${use_peer_sip};;
extension) return 0;;
*) return 1;;
esac
}
ast_add_conf sip
init_sipconf() {
ast_add_reload sip
ast_enable_type sipgeneral
ast_enable_type sip
ast_enable_type target
sip_opt_port=5060
sip_opt_bindaddr=0.0.0.0
sip_opt_context=default
sip_opt_maxexpirey=3600
sip_opt_defaultexpirey=3600
sip_opt_notifymimetype=text/plain
sip_opt_rtptimeout=60
sip_opt_rtpholdtimeout=300
config_get WAN_IP wan ipaddr
# TODO check why the above does not work all the time
if [ -z "${WAN_IP}" ] ; then
config_get WAN_IF wan ifname
WAN_IP=$(ifconfig ${WAN_IF} | grep "inet addr:" | sed 's/^.*inet addr:\([^ ]*\) .*$/\1/')
fi
sip_opt_externip=${WAN_IP}
sip_opt_realm=asterisk
config_get LAN_MASK lan netmask
config_get LAN_IP lan ipaddr
LAN_NET=$(/bin/ipcalc.sh $LAN_IP $LAN_MASK | grep NETWORK | cut -d= -f2)
sip_opt_localnet=$LAN_NET/$LAN_MASK
# default to ulaw only
sip_opt_allow=
sip_opt_registertimeout=20
sip_opt_registerattempts=10
sip_opt_canreinvite=no
sip_sections=
}
sip_list="port bindaddr context maxexpirey defaultexpirey notifymimetype \
rtptimeout rtpholdtimeout realm domain localnet externip"
create_sipconf() {
append_dialplan_locals
file=${DEST_DIR}/sip.conf
get_checksum sip_conf $file
local isempty=1
if [ -z "${sip_sections}" ] ; then
rm -f $file
isempty=2
else
[ -z "${sip_opt_domain}" ] && sip_opt_domain=${sip_opt_realm}
echo "${asteriskuci_gen}[general]" > $file
for i in ${sip_list} ; do
eval value=\$sip_opt_$i
[ ! -z "$value" ] && ( echo "$i=$value" >> $file )
done
echo "disallow=all" >> $file
local rhs="${sip_opt_allow}"
if [ -z "$rhs" ] ; then
rhs=ulaw
fi
while [ ! -z "$rhs" ] ; do
cur=${rhs%%,*}
nvar=${rhs#*,}
enable_format ${cur}
echo "allow=${cur}" >> $file
[ "$nvar" == "$rhs" ] && break
rhs=${nvar}
done
echo "${N}${sip_register}${N}${N}${sip_sections}" >> $file
unset sip_register
unset sip_sections
fi
check_checksum "$sip_conf" "$file" || ast_sip_restart=$isempty
}
handle_sipgeneral() {
option_cb(){
if valid_sipiax_option globalsip $1 $2 ; then
case "$1" in
host)
if [ -z "$2" ] ; then
sip_opt_host=dynamic
else
sip_opt_host="$2"
fi ;;
allow_LENGTH) ;;
allow|allow_ITEM*)
append sip_opt_allow "$2" "," ;;
*) eval "sip_opt_$1=\"\$2\"" ;;
esac
elif valid_rtp_option $1 $2 ; then
eval "rtp_opt_$1=\"\$2\""
else
logerror "Invalid SIP global option: $1"
fi
}
}
handle_sip() {
check_add sipitems
append sip_sections [$1] "$N$N"
enable_module chan_sip
sip_sectionname=${1#sip_}
sip_type=peer
sip_doregister=0
sip_last_context=-
sip_last_doregister=-
sip_selfmailbox=no
option_cb() {
logdebug 3 "SIP/${sip_sectionname}: '$1' '$2'"
case $1 in
type) sip_type=$2
append sip_sections "$1=$2" "$N"
;;
register)
if [ "$2" == "yes" ]; then
sip_doregister=1
fi ;;
registerextension) eval sip_last_$1="$2";;
allow|allow_ITEM*) split_append sip_sections allow= "$2" "${N}" enable_format ;;
extension|extension_ITEM*) add_extension SIP ${sip_sectionname} "$2" ;;
context) sip_last_context="$2" ;;
selfmailbox) sip_selfmailbox="$2" ;;
incoming|incoming_ITEM*)
add_incoming SIP ${sip_sectionname} "$2" ;;
timeout|prefix|internationalprefix|alwaysinternational|countrycode)
eval "target_$1_SIP_${sectionname}=\"$2\""
;;
allow_LENGTH|incoming_LENGTH|extension_LENGTH) ;;
*)
eval sip_last_$1="$2"
if valid_sipiax_option ${sip_type}sip $1 $2 ; then
append sip_sections "$1=$2" "$N"
else
logerror "Invalid SIP option for ${sip_type}: $1"
fi
esac
}
}
# rtp.conf
ast_add_conf rtp
init_rtpconf() {
ast_add_reload rtp
rtp_opt_rtpstart=5000
rtp_opt_rtpend=31000
rtp_opt_rtpchecksums=
rtp_opt_rtpdtmftimeout=
rtp_opt_rtcpinterval=5000
}
create_rtpconf() {
file=${DEST_DIR}/rtp.conf
get_checksum rtp_conf $file
local isempty=1
if module_enabled chan_sip ; then
echo "${asteriskuci_gen}[general]" > $file
for i in $rtp_option_list ; do
eval "local val=\"\$rtp_opt_$i\""
if [ ! -z "$val" ] ; then
lhs=$i
case "$i" in
rtpdtmftimeout) lhs=dtmftimeout
esac
echo "$lhs=$val" >> $file
fi
done
else
rm -f $file
isempty=2
fi
check_checksum "$rtp_conf" "$file" || ast_rtp_restart=$isempty
}
reload_rtp() astcmd "rtp reload"
unload_rtp() astcmd "unload rtp"
# Iax
ast_add_conf iax
init_iaxconf() {
ast_add_reload iax
ast_enable_type iaxgeneral
ast_enable_type iax
return 0
}
create_iaxconf() {
local file=$DEST_DIR/iax.conf
get_checksum iax_conf $file
local isempty=1
if [ -z "${iax_sections}" ] ; then
rm -f $file
isempty=2
else
echo "${asteriskuci_gen}${iax_general}$N$N${iax_sections}" > $file
fi
check_checksum "$iax_conf" "$file" || ast_iax_restart=${isempty}
}
handle_iaxgeneral() {
iax_general="[general]"
option_cb() {
case $1 in
allow_LENGTH) ;;
allow|allow_ITEM*) split_append iax_general allow= "$2" "${N}" enable_format ;;
*)
if valid_sipiax_option globaliax $1 $2 ; then
eval "iax_opt_$1=\"$2\""
append iax_general "$1=$2" "$N"
else
logerror "Invalid IAX global option: $1"
fi ;;
esac
}
}
handle_iax() {
check_add iaxitems
append iax_sections "[$1]" "$N$N"
iax_type=peer
iax_sectionname="${1#iax_}"
iax_last_context=-
iax_selfmailbox=no
enable_module chan_iax2
option_cb() {
case $1 in
type)
iax_type=$2
append iax_sections "type=$2" "$N" ;;
allow_LENGTH) ;;
allow|allow_ITEM*)
split_append iax_sections allow= "$2" "${N}" enable_format ;;
extension)
logdebug 1 "Adding IAX extension $2 for $iax_sectionname"
eval [ -z "\${dialplan_ext_$2}" ] && dialplan_exts="${dialplan_exts} $2"
iax_last_extension="$2"
append dialplan_ext_$2 "IAX2/${iax_sectionname}" "&" ;;
extension) add_extension IAX ${iax_sectionname} "$2" ;;
context)
eval iax_last_context="$2" ;;
selfmailbox)
eval iax_selfmailbox="$2" ;;
incoming)
add_incoming IAX ${iax_sectionname} "$3" ;;
timeout|prefix|internationalprefix|alwaysinternational|countrycode)
eval "target_$1_IAX_${sectionname}=\"$2\"" ;;
*)
eval iax_last_$1="$2"
if valid_sipiax_option ${iax_type}iax $1 $2 ; then
append iax_sections "$1=$2" "$N"
else
logerror "Invalid IAX option for ${iax_type}: $1"
fi
esac
}
}
reload_iax() {
astcmd "iax2 reload"
return 1
}
unload_iax() astcmd "unload chan_iax2.so"
handle_target() {
# Target name
targettype=${1%[-_]*}
if [ ${targettype} == $1 ] ; then
logerror "No target type specified (SIP-$1 IAX-$1)"
return 1
fi
targetname=${1#*[-_]}
case $targettype in
[Ss][Ii][Pp]) handle_dialtarget SIP $targetname ;;
[Ii][Aa][Xx]) handle_dialtarget IAX $targetname ;;
*) logerror "Invalid target type specified: $targettype"
esac
}
# Set up options sip/iax targets for outgoing sip/iax
handle_dialtarget() {
# Dialzone target option
areatype=$1
areaname=$2
logdebug 1 "Dialzone Target for ${areatype}/${areaname}"
option_cb(){
case $1 in
timeout|prefix|internationalprefix|alwaysinternational|countrycode)
eval target_$1_${areatype}_${areaname}=$2
;;
*)
logerror "Invalid target for $areatype/$areaname: ${1}"
esac
}
}
# vim: ts=2 sw=2 noet foldmethod=indent

View file

@ -0,0 +1,114 @@
target (SIP|IAX)_{name} - Handle options for outgoing dialing
timeout - Timeout for dialing out with this target
prefix - Prefix required to dial out on this target
internationalprefix- Prefix required to dial internation on this target
alwaysinternational- True if this target always requires internation prefix
countrycode - Default International country code for this target
sipgeneral
sip [sip_]{name}
type - Type of sip connection - very important.
register - Set to yes to register
registerextension - 'Extension' to use in register string in place of username
extension - Extension to use for this phone (doesn't have to be unique)
selfmailbox - Set to yes to have dialing own extensions go to mailbox
incoming (list) - Specify the incoming context for ringing
timeout - Timeout for dialing out with this target
prefix - Prefix required to dial out on this target
internationalprefix- Prefix required to dial internation on this target
alwaysinternational- True if this target always requires internation prefix
countrycode - Default International country code for this target
rtpstart - rtp.conf option
rtpend - rtp.conf option
rtpdtmftimeout - rtp.conf option dtmftimeout
rtcpinterval - rtp.conf option
rtpchecksums - rtp.conf option
iaxgeneral
iax [iax_]{name}
extension Extensions to use for this phone
selfmailbox - Set to yes to have dialing own extensions go to mailbox
incoming (list) - Specify the incoming context for ringing
timeout - Timeout for dialing out with this target
prefix - Prefix required to dial out on this target
internationalprefix- Prefix required to dial internation on this target
alwaysinternational- True if this target always requires internation prefix
countrycode - Default International country code for this target
General asterisk options - see asterisk doco
Options |Type |sip |sip |iax |iax
| |general| |general|
-----------------+--------+-------+-----+-------+-----
writeprotect Integer no no yes yes
static Integer no no yes yes
port Integer yes yes no no
maxexpirey Integer yes yes no no
rtptimeout Integer yes yes no no
rtpholdtimeout Integer yes yes no no
defaultexpirey Integer yes yes no no
registertimeout Integer yes yes no no
registerattempts Integer yes yes no no
call-limit Integer yes yes no no
# ip addr
bindaddr IP Addr yes yes no no
externip IP Addr yes yes no no
localnet Net/mask yes yes no no
permit Net/mask no yes no no
deny Net/mask no yes no no
realm Domain yes yes no no
domain Domain yes yes no no
context context yes yes yes yes
notifymimetype Mimetype yes yes no no
canreinvite Yes/No yes yes yes yes
nat Yes/No yes yes no no
allowoverlap Yes/No yes yes no no
allowsubscribe Yes/No yes yes no no
allowtransfer Yes/No yes yes no no
videosupport Yes/No yes yes no no
pedantic Yes/No no yes no no
trustrpid, Yes/No no yes no no
promiscredir Yes/No no yes no no
useclientcode Yes/No no yes no no
dtmfmode Enum yes yes no no
type Enum no yes no yes
insecure Enum no yes no no
callingpres Enum no yes no no
progressinband Enum no yes no no
allow List yes yes yes yes
disallow List yes yes yes yes
register Register yes yes no no
username String no yes no yes
secret String no yes no yes
md5secret String no yes no yes
host String no yes no yes
mailbox String no yes no yes
auth String no no no yes
callgroup String no yes no no
pickupgroup String no yes no no
language String no yes no no
accountcode String no yes no no
setvar String no yes no no
callerid String no yes no no
amaflags String no yes no no
subscribecontext String no yes no no
maxcallbitrate String no yes no no
rfc2833compensate String no yes no no
mailbox String no yes no no
template String no peer no no
fromdomain String no peer no no
regexten String no peer no no
fromuser String no peer no no
qualify String no peer no no
defaultip String no peer no no
sendrpid String no peer no no
outboundproxy String no peer no no

View file

@ -0,0 +1,48 @@
#!/bin/sh
ast_add_module clock
init_clock() {
ast_enable_type dialplanclock
}
add_dialplan_talkclock() {
local context=$1
local zone=${asterisk_zone}
[ ! -z "$3" ] && zone="$3"
local date_format="$4"
local time_format="$5"
logdebug 1 "Adding Dialplan talking clock $1 $2"
check_add_context "$context"
local ext="exten => $2,"
if [ "${dialplan_add_include_clock}" != 1 ] ; then
dialplan_add_include_clock=1
enable_format gsm
enable_module app_sayunixtime
append_include "macros/clock.conf"
fi
append dialplan_context_${context} "${ext}1,Macro(talkingclock,${time_format},${date_format},${zone})" "${N}"
}
handle_dialplanclock() {
check_add dialplanclock
option_cb() {
case $1 in
dialplan|extension|zone|timeformat|dateformat)
eval "dial_clock_$1=\"$2\"" ;;
esac
}
}
check_add_dialplanclock() {
if [ ! -z "${dial_clock_extension}" ] ; then
[ -z ${dial_clock_dialplan} ] && dial_clock_dialplan=default
add_dialplan_talkclock "${dial_clock_dialplan}" "${dial_clock_extension}" \
"${dial_clock_zone}" "${dial_clock_dateformat}" "${dial_clock_timeformat}"
fi
for i in dialplan extension zone timeformat dateformat ; do
eval "unset dial_clock_$i"
done
}
# vim: ts=2 sw=2 noet foldmethod=indent

View file

@ -0,0 +1,7 @@
dialplanclock
dialplan - dialplan to add clock to
extension - extensions for talking clock
zone - Timezone to use
timeformat - Time Format to use
dateformat - Date format to use

View file

@ -0,0 +1,217 @@
#!/bin/sh
# Voicemail.conf
ast_add_conf voicemail
init_voicemailconf() {
ast_add_reload voicemail
ast_enable_type voicegeneral
ast_enable_type voicemail
ast_enable_type voicezone
ast_enable_type dialplanvoice
voice_format="wav49|gsm|wav"
voice_serveremail=
voice_attach=no
voice_skipms=3000
voice_maxsilence=10
voice_silencethreshold=128
voice_maxlogins=3
voice_emaildateformat="%A, %B %d, %Y at %r"
voice_sendvoicemail=no
voice_maxmsg=100
voice_maxmessage=180
voice_minmessage=3
voice_maxgreet=60
return 0
}
voicegeneral_list="format serveremail attach skipms maxsilence silencethreshold maxlogins emaildateformat sendvoicemail maxmsg maxmessage minmessage maxgreet"
voicegeneral_ext_list=""
valid_voicemail(){
is_in_list $1 ${voicegeneral_list} ${voicegeneral_ext_list}
return $?
}
voicebox_list="context number password name email pager"
voicebox_listopt="tz attach serveremail saycid dialout callback review operator envelope sayduration saydurationm"
valid_voicebox() {
is_in_list $1 ${voicebox_list} ${voicebox_listopt}
return $?
}
check_add_voicebox() {
if [ ! -z ${voicebox_number} ] ; then
[ -z "${voicebox_context}" ] && voicebox_context=default
logdebug 1 "Adding Voicebox ${voicebox_number} in ${voicebox_context}"
# Construct the voicebox line
local line="$voicebox_number => "
[ -z ${voicebox_tz} ] && voicebox_tz=homeloc
[ -z ${voicebox_name} ] && voicebox_name=OpenWRT
for i in password name email pager ; do
eval "local value=\"\${voicebox_$i}\""
line="${line}${value},"
done
# Then add named options.
for i in ${voicebox_listopt} ; do
eval val=\${voicebox_$i}
[ -z ${val} ] || append line "$i=$val" \|
done
# Check if the current voicebox context has anything
eval local cur=\${voicebox_section_$voicebox_context}
# if not add it to the list of contexts used
[ -z $cur ] && append voice_contextlist "${voicebox_context}" " "
# Then add the voicebox line to the context
logdebug 4 "Add Voicebox $line to ${voicebox_context}"
append voicebox_section_${voicebox_context} "$line" "$N"
fi
# Then clear the settings for the next one.
for i in ${voicebox_list} ${voicebox_listopt} ; do
eval unset voicebox_$i
done
}
create_voicemailconf() {
# Construct the file
file=${DEST_DIR}/voicemail.conf
get_checksum voicemail_conf $file
local isempty=1
if [ -z ${voice_contextlist} ] ; then
local isempty=2
rm -f $file
else
echo "${asteriskuci_gen}[general]" > $file
for i in ${voicegeneral_list} ; do
eval value=\${voice_$i}
if [ ! -z "$value" ] ; then
echo "$i=$value" >> $file
fi
done
echo "${N}[zonemessages]" >> $file
echo "homeloc=${asterisk_zone}| Q IMp" >> $file
echo "${voicezone_list}" >> $file
for i in ${voice_contextlist} ; do
echo "${N}[$i]" >> $file
eval "local cursection=\"\${voicebox_section_${i}}\""
echo "$cursection" >> $file
eval unset voicebox_section_${i}
done
unset voice_contexts
fi
check_checksum "$voicemail_conf" "$file" || ast_voicemail_restart=$isempty
}
handle_voicegeneral() {
option_cb() {
if valid_voicemail $1 $2 ; then
eval voice_$1="$2"
else
logerror "Invalid general voice option: $1"
fi
}
}
handle_voicemail() {
check_add voicebox
voicebox_context=${1%[-_]*}
if [ ${voicebox_context} == $1 ] ; then
voicebox_context=default
fi
voicebox_number=${1#*[-_]}
option_cb() {
case $1 in
zone) voicebox_tz="$2" ;;
*)
if valid_voicebox $1 $2 ; then
eval voicebox_$1="$2"
else
logerror "Invalid voicebox option: $1"
fi
esac
}
}
# Locality options for voicemail
check_add_voicezone() {
if [ ! -z "${voicezone_name}" ] ; then
[ -z "${voicezone_zone}" ] && voicezone_zone=${asterisk_zone}
if [ -z "${voicezone_message}" ] ; then
voicezone_message="Q IMp"
else
voicezone_message=`echo "$voicezone_message"|tr \" \'`
fi
append voicezone_list "${voicezone_name}=${voicezone_zone}|${voicezone_message}" "${N}"
fi
unset voicezone_name
unset voicezone_zone
unset voicezone_message
}
handle_voicezone() {
voicezone_name=$1
option_cb() {
case $1 in
zone) voicezone_zone="$2" ;;
message) voicezone_message="$2" ;;
*) logerror "Invalid voicezone option: $1"
esac
}
}
handle_dialplanvoice() {
check_add dialplanvoice
option_cb() {
case $1 in
dialplan|extension|voicecontext|voicebox)
eval "dial_voice_$1=\"$2\"" ;;
*) logerror "Invalid option: $1 for dialplanvoice"
esac
}
}
check_add_dialplanvoice() {
if [ ! -z "${dial_voice_dialplan}" -a ! -z "${dial_voice_extension}" ] ; then
local ext="exten => ${dial_voice_extension},"
[ -z ${dial_voice_voicebox} ] && dial_voice_voicebox=default
if [ -z ${dial_voice_voicebox} ] ; then
logerror "Expecting voicebox for ${dial_voice_dialplan}/${dial_voice_extension}"
else
check_add_context ${dial_voice_dialplan}
local voiceext="${dial_voice_voicebox}@${dial_voice_voicecontext}"
enable_voicemail
append dialplan_context_${dial_voice_dialplan} "${ext}1,VoiceMailMain(${voiceext})" "${N}"
fi
fi
for i in dialplan extension voicecontext voicebox ; do
eval "unset dial_voice_$i"
done
}
add_dialplan_voice() {
local context=$1
logdebug 1 "Adding Dialplan voice $1 $2"
check_add_context "$context"
local ext="exten => $2,"
enable_voicemail
append dialplan_context_${context} "${ext}1,VoiceMailMain($3)" "${N}"
}
reload_voicemail() astcmd "module reload app_voicemail.so"
unload_voicemail() astcmd "module unload app_voicemail.so"
# vim: ts=2 sw=2 noet foldmethod=indent

View file

@ -0,0 +1,12 @@
diff -Nru asterisk-1.4.22.org/main/Makefile asterisk-1.4.22/main/Makefile
--- asterisk-1.4.22.org/main/Makefile 2008-07-18 18:15:41.000000000 +0200
+++ asterisk-1.4.22/main/Makefile 2008-11-29 14:58:13.000000000 +0100
@@ -144,7 +144,7 @@
ifneq ($(findstring chan_h323,$(MENUSELECT_CHANNELS)),)
$(CMD_PREFIX) $(CC) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $^ buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS)
else
- $(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $(H323LDFLAGS) $^ buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(H323LDLIBS)
+ $(CMD_PREFIX) $(CC) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $(H323LDFLAGS) $^ buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(H323LDLIBS)
endif
$(CMD_PREFIX) $(ASTTOPDIR)/build_tools/strip_nonapi $@ || rm $@

View file

@ -0,0 +1,12 @@
diff -Nru asterisk-1.4.22.org/channels/chan_iax2.c asterisk-1.4.22/channels/chan_iax2.c
--- asterisk-1.4.22.org/channels/chan_iax2.c 2008-09-02 20:14:57.000000000 +0200
+++ asterisk-1.4.22/channels/chan_iax2.c 2008-11-29 15:00:00.000000000 +0100
@@ -1815,7 +1815,7 @@
last++;
else
last = s;
- snprintf(s2, strlen(s) + 100, "/var/tmp/%s-%ld", last, (unsigned long)ast_random());
+ snprintf(s2, strlen(s) + 100, "/tmp/%s-%ld", last, (unsigned long)ast_random());
res = stat(s, &stbuf);
if (res < 0) {
ast_log(LOG_WARNING, "Failed to stat '%s': %s\n", s, strerror(errno));

View file

@ -0,0 +1,12 @@
diff -Nru asterisk-1.4.22.org/configure.ac asterisk-1.4.22/configure.ac
--- asterisk-1.4.22.org/configure.ac 2008-09-08 18:26:00.000000000 +0200
+++ asterisk-1.4.22/configure.ac 2008-11-29 15:01:13.000000000 +0100
@@ -1319,7 +1319,7 @@
AST_EXT_LIB_CHECK([SQLITE], [sqlite], [sqlite_exec], [sqlite.h])
-AST_EXT_LIB_CHECK([OPENSSL], [ssl], [ssl2_connect], [openssl/ssl.h], [-lcrypto])
+AST_EXT_LIB_CHECK([OPENSSL], [ssl], [ssl23_connect], [openssl/ssl.h], [-lcrypto])
if test "$PBX_OPENSSL" = "1";
then
AST_EXT_LIB_CHECK([OSPTK], [osptk], [OSPPCryptoDecrypt], [osp/osp.h], [-lcrypto -lssl])

View file

@ -0,0 +1,875 @@
diff -Nru asterisk-1.4.22.org/apps/app_rxfax.c asterisk-1.4.22/apps/app_rxfax.c
--- asterisk-1.4.22.org/apps/app_rxfax.c 1970-01-01 01:00:00.000000000 +0100
+++ asterisk-1.4.22/apps/app_rxfax.c 2008-11-29 15:02:27.000000000 +0100
@@ -0,0 +1,376 @@
+/*
+ * Asterisk -- A telephony toolkit for Linux.
+ *
+ * Trivial application to receive a TIFF FAX file
+ *
+ * Copyright (C) 2003, Steve Underwood
+ *
+ * Steve Underwood <steveu@coppice.org>
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License
+ */
+
+/*** MODULEINFO
+ <depend>spandsp</depend>
+***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision:$")
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <errno.h>
+#include <tiffio.h>
+
+#include <spandsp.h>
+
+#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 "asterisk/manager.h"
+
+static char *app = "RxFAX";
+
+static char *synopsis = "Receive a FAX to a file";
+
+static char *descrip =
+" RxFAX(filename[|caller][|debug]): Receives a FAX from the channel into the\n"
+"given filename. If the file exists it will be overwritten. The file\n"
+"should be in TIFF/F format.\n"
+"The \"caller\" option makes the application behave as a calling machine,\n"
+"rather than the answering machine. The default behaviour is to behave as\n"
+"an answering machine.\n"
+"Uses LOCALSTATIONID to identify itself to the remote end.\n"
+" LOCALHEADERINFO to generate a header line on each page.\n"
+"Sets REMOTESTATIONID to the sender CSID.\n"
+" FAXPAGES to the number of pages received.\n"
+" FAXBITRATE to the transmition rate.\n"
+" FAXRESOLUTION to the resolution.\n"
+"Returns -1 when the user hangs up.\n"
+"Returns 0 otherwise.\n";
+
+#define MAX_BLOCK_SIZE 240
+
+static void span_message(int level, const char *msg)
+{
+ int ast_level;
+
+ if (level == SPAN_LOG_WARNING)
+ ast_level = __LOG_WARNING;
+ else if (level == SPAN_LOG_WARNING)
+ ast_level = __LOG_WARNING;
+ else
+ ast_level = __LOG_DEBUG;
+ ast_log(ast_level, __FILE__, __LINE__, __PRETTY_FUNCTION__, msg);
+}
+/*- End of function --------------------------------------------------------*/
+
+static void t30_flush(t30_state_t *s, int which)
+{
+ /* TODO: */
+}
+/*- End of function --------------------------------------------------------*/
+
+static void phase_e_handler(t30_state_t *s, void *user_data, int result)
+{
+ struct ast_channel *chan;
+ t30_stats_t t;
+ char local_ident[21];
+ char far_ident[21];
+ char buf[11];
+
+ chan = (struct ast_channel *) user_data;
+ if (result == T30_ERR_OK)
+ {
+ t30_get_transfer_statistics(s, &t);
+ t30_get_far_ident(s, far_ident);
+ t30_get_local_ident(s, local_ident);
+ ast_log(LOG_DEBUG, "==============================================================================\n");
+ ast_log(LOG_DEBUG, "Fax successfully received.\n");
+ ast_log(LOG_DEBUG, "Remote station id: %s\n", far_ident);
+ ast_log(LOG_DEBUG, "Local station id: %s\n", local_ident);
+ ast_log(LOG_DEBUG, "Pages transferred: %i\n", t.pages_transferred);
+ ast_log(LOG_DEBUG, "Image resolution: %i x %i\n", t.x_resolution, t.y_resolution);
+ ast_log(LOG_DEBUG, "Transfer Rate: %i\n", t.bit_rate);
+ ast_log(LOG_DEBUG, "==============================================================================\n");
+ manager_event(EVENT_FLAG_CALL,
+ "FaxReceived", "Channel: %s\nExten: %s\nCallerID: %s\nRemoteStationID: %s\nLocalStationID: %s\nPagesTransferred: %i\nResolution: %i\nTransferRate: %i\nFileName: %s\n",
+ chan->name,
+ chan->exten,
+ (chan->cid.cid_num) ? chan->cid.cid_num : "",
+ far_ident,
+ local_ident,
+ t.pages_transferred,
+ t.y_resolution,
+ t.bit_rate,
+ s->rx_file);
+ pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", far_ident);
+ snprintf(buf, sizeof(buf), "%i", t.pages_transferred);
+ pbx_builtin_setvar_helper(chan, "FAXPAGES", buf);
+ snprintf(buf, sizeof(buf), "%i", t.y_resolution);
+ pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", buf);
+ snprintf(buf, sizeof(buf), "%i", t.bit_rate);
+ pbx_builtin_setvar_helper(chan, "FAXBITRATE", buf);
+ }
+ else
+ {
+ ast_log(LOG_DEBUG, "==============================================================================\n");
+ ast_log(LOG_DEBUG, "Fax receive not successful - result (%d) %s.\n", result, t30_completion_code_to_str(result));
+ ast_log(LOG_DEBUG, "==============================================================================\n");
+ }
+}
+/*- End of function --------------------------------------------------------*/
+
+static void phase_d_handler(t30_state_t *s, void *user_data, int result)
+{
+ struct ast_channel *chan;
+ t30_stats_t t;
+
+ chan = (struct ast_channel *) user_data;
+ if (result)
+ {
+ t30_get_transfer_statistics(s, &t);
+ ast_log(LOG_DEBUG, "==============================================================================\n");
+ ast_log(LOG_DEBUG, "Pages transferred: %i\n", t.pages_transferred);
+ ast_log(LOG_DEBUG, "Image size: %i x %i\n", t.width, t.length);
+ ast_log(LOG_DEBUG, "Image resolution %i x %i\n", t.x_resolution, t.y_resolution);
+ ast_log(LOG_DEBUG, "Transfer Rate: %i\n", t.bit_rate);
+ ast_log(LOG_DEBUG, "Bad rows %i\n", t.bad_rows);
+ ast_log(LOG_DEBUG, "Longest bad row run %i\n", t.longest_bad_row_run);
+ ast_log(LOG_DEBUG, "Compression type %i\n", t.encoding);
+ ast_log(LOG_DEBUG, "Image size (bytes) %i\n", t.image_size);
+ ast_log(LOG_DEBUG, "==============================================================================\n");
+ }
+}
+/*- End of function --------------------------------------------------------*/
+
+static int rxfax_exec(struct ast_channel *chan, void *data)
+{
+ int res = 0;
+ char template_file[256];
+ char target_file[256];
+ char *s;
+ char *t;
+ char *v;
+ const char *x;
+ int option;
+ int len;
+ int i;
+ fax_state_t fax;
+ int calling_party;
+ int verbose;
+ int samples;
+
+ struct ast_module_user *u;
+ struct ast_frame *inf = NULL;
+ struct ast_frame outf;
+
+ int original_read_fmt;
+ int original_write_fmt;
+
+ uint8_t __buf[sizeof(uint16_t)*MAX_BLOCK_SIZE + 2*AST_FRIENDLY_OFFSET];
+ uint8_t *buf = __buf + AST_FRIENDLY_OFFSET;
+
+ if (chan == NULL)
+ {
+ ast_log(LOG_WARNING, "Fax receive channel is NULL. Giving up.\n");
+ return -1;
+ }
+
+ span_set_message_handler(span_message);
+
+ /* The next few lines of code parse out the filename and header from the input string */
+ if (data == NULL)
+ {
+ /* No data implies no filename or anything is present */
+ ast_log(LOG_WARNING, "Rxfax requires an argument (filename)\n");
+ return -1;
+ }
+
+ calling_party = FALSE;
+ verbose = FALSE;
+ target_file[0] = '\0';
+
+ for (option = 0, v = s = data; v; option++, s++)
+ {
+ t = s;
+ v = strchr(s, '|');
+ s = (v) ? v : s + strlen(s);
+ strncpy((char *) buf, t, s - t);
+ buf[s - t] = '\0';
+ if (option == 0)
+ {
+ /* The first option is always the file name */
+ len = s - t;
+ if (len > 255)
+ len = 255;
+ strncpy(target_file, t, len);
+ target_file[len] = '\0';
+ /* Allow the use of %d in the file name for a wild card of sorts, to
+ create a new file with the specified name scheme */
+ if ((x = strchr(target_file, '%')) && x[1] == 'd')
+ {
+ strcpy(template_file, target_file);
+ i = 0;
+ do
+ {
+ snprintf(target_file, 256, template_file, 1);
+ i++;
+ }
+ while (ast_fileexists(target_file, "", chan->language) != -1);
+ }
+ }
+ else if (strncmp("caller", t, s - t) == 0)
+ {
+ calling_party = TRUE;
+ }
+ else if (strncmp("debug", t, s - t) == 0)
+ {
+ verbose = TRUE;
+ }
+ }
+
+ /* Done parsing */
+
+ u = ast_module_user_add(chan);
+
+ if (chan->_state != AST_STATE_UP)
+ {
+ /* Shouldn't need this, but checking to see if channel is already answered
+ * Theoretically asterisk should already have answered before running the app */
+ res = ast_answer(chan);
+ }
+
+ if (!res)
+ {
+ original_read_fmt = chan->readformat;
+ if (original_read_fmt != AST_FORMAT_SLINEAR)
+ {
+ res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
+ if (res < 0)
+ {
+ ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
+ return -1;
+ }
+ }
+ original_write_fmt = chan->writeformat;
+ if (original_write_fmt != AST_FORMAT_SLINEAR)
+ {
+ res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
+ if (res < 0)
+ {
+ ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
+ res = ast_set_read_format(chan, original_read_fmt);
+ if (res)
+ ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
+ return -1;
+ }
+ }
+ fax_init(&fax, calling_party);
+ if (verbose)
+ fax.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
+ x = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
+ if (x && x[0])
+ t30_set_local_ident(&fax.t30_state, x);
+ x = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO");
+ if (x && x[0])
+ t30_set_header_info(&fax.t30_state, x);
+ t30_set_rx_file(&fax.t30_state, target_file, -1);
+ //t30_set_phase_b_handler(&fax.t30_state, phase_b_handler, chan);
+ t30_set_phase_d_handler(&fax.t30_state, phase_d_handler, chan);
+ t30_set_phase_e_handler(&fax.t30_state, phase_e_handler, chan);
+ t30_set_ecm_capability(&fax.t30_state, TRUE);
+ t30_set_supported_compressions(&fax.t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
+ while (ast_waitfor(chan, -1) > -1)
+ {
+ inf = ast_read(chan);
+ if (inf == NULL)
+ {
+ res = -1;
+ break;
+ }
+ if (inf->frametype == AST_FRAME_VOICE)
+ {
+ if (fax_rx(&fax, inf->data, inf->samples))
+ break;
+ samples = (inf->samples <= MAX_BLOCK_SIZE) ? inf->samples : MAX_BLOCK_SIZE;
+ len = fax_tx(&fax, (int16_t *) &buf[AST_FRIENDLY_OFFSET], samples);
+ if (len)
+ {
+ memset(&outf, 0, sizeof(outf));
+ outf.frametype = AST_FRAME_VOICE;
+ outf.subclass = AST_FORMAT_SLINEAR;
+ outf.datalen = len*sizeof(int16_t);
+ outf.samples = len;
+ outf.data = &buf[AST_FRIENDLY_OFFSET];
+ outf.offset = AST_FRIENDLY_OFFSET;
+ outf.src = "RxFAX";
+ if (ast_write(chan, &outf) < 0)
+ {
+ ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno));
+ break;
+ }
+ }
+ }
+ ast_frfree(inf);
+ }
+ if (inf == NULL)
+ {
+ ast_log(LOG_DEBUG, "Got hangup\n");
+ res = -1;
+ }
+ if (original_read_fmt != AST_FORMAT_SLINEAR)
+ {
+ res = ast_set_read_format(chan, original_read_fmt);
+ if (res)
+ ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
+ }
+ if (original_write_fmt != AST_FORMAT_SLINEAR)
+ {
+ res = ast_set_write_format(chan, original_write_fmt);
+ if (res)
+ ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", chan->name);
+ }
+ t30_terminate(&fax.t30_state);
+ }
+ else
+ {
+ ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
+ }
+ ast_module_user_remove(u);
+ return res;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int unload_module(void)
+{
+ int res;
+
+ ast_module_user_hangup_all();
+
+ res = ast_unregister_application(app);
+
+
+ return res;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int load_module(void)
+{
+ return ast_register_application(app, rxfax_exec, synopsis, descrip);
+}
+/*- End of function --------------------------------------------------------*/
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Trivial FAX Receive Application");
+
+/*- End of file ------------------------------------------------------------*/
diff -Nru asterisk-1.4.22.org/apps/app_txfax.c asterisk-1.4.22/apps/app_txfax.c
--- asterisk-1.4.22.org/apps/app_txfax.c 1970-01-01 01:00:00.000000000 +0100
+++ asterisk-1.4.22/apps/app_txfax.c 2008-11-29 15:02:27.000000000 +0100
@@ -0,0 +1,303 @@
+/*
+ * Asterisk -- A telephony toolkit for Linux.
+ *
+ * Trivial application to send a TIFF file as a FAX
+ *
+ * Copyright (C) 2003, Steve Underwood
+ *
+ * Steve Underwood <steveu@coppice.org>
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License
+ */
+
+/*** MODULEINFO
+ <depend>spandsp</depend>
+***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision:$")
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <errno.h>
+#include <tiffio.h>
+
+#include <spandsp.h>
+
+#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"
+
+static char *app = "TxFAX";
+
+static char *synopsis = "Send a FAX file";
+
+static char *descrip =
+" TxFAX(filename[|caller][|debug]): Send a given TIFF file to the channel as a FAX.\n"
+"The \"caller\" option makes the application behave as a calling machine,\n"
+"rather than the answering machine. The default behaviour is to behave as\n"
+"an answering machine.\n"
+"Uses LOCALSTATIONID to identify itself to the remote end.\n"
+" LOCALHEADERINFO to generate a header line on each page.\n"
+"Sets REMOTESTATIONID to the receiver CSID.\n"
+"Returns -1 when the user hangs up, or if the file does not exist.\n"
+"Returns 0 otherwise.\n";
+
+#define MAX_BLOCK_SIZE 240
+
+static void span_message(int level, const char *msg)
+{
+ int ast_level;
+
+ if (level == SPAN_LOG_WARNING)
+ ast_level = __LOG_WARNING;
+ else if (level == SPAN_LOG_WARNING)
+ ast_level = __LOG_WARNING;
+ else
+ ast_level = __LOG_DEBUG;
+ ast_log(ast_level, __FILE__, __LINE__, __PRETTY_FUNCTION__, msg);
+}
+/*- End of function --------------------------------------------------------*/
+
+#if 0
+static void t30_flush(t30_state_t *s, int which)
+{
+ /* TODO: */
+}
+/*- End of function --------------------------------------------------------*/
+#endif
+
+static void phase_e_handler(t30_state_t *s, void *user_data, int result)
+{
+ struct ast_channel *chan;
+ char far_ident[21];
+
+ chan = (struct ast_channel *) user_data;
+ if (result == T30_ERR_OK)
+ {
+ t30_get_far_ident(s, far_ident);
+ pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", far_ident);
+ }
+ else
+ {
+ ast_log(LOG_DEBUG, "==============================================================================\n");
+ ast_log(LOG_DEBUG, "Fax send not successful - result (%d) %s.\n", result, t30_completion_code_to_str(result));
+ ast_log(LOG_DEBUG, "==============================================================================\n");
+ }
+}
+/*- End of function --------------------------------------------------------*/
+
+static int txfax_exec(struct ast_channel *chan, void *data)
+{
+ int res = 0;
+ char source_file[256];
+ char *s;
+ char *t;
+ char *v;
+ const char *x;
+ int option;
+ int len;
+ fax_state_t fax;
+ int calling_party;
+ int verbose;
+ int samples;
+
+ struct ast_module_user *u;
+ struct ast_frame *inf = NULL;
+ struct ast_frame outf;
+
+ int original_read_fmt;
+ int original_write_fmt;
+
+ uint8_t __buf[sizeof(uint16_t)*MAX_BLOCK_SIZE + 2*AST_FRIENDLY_OFFSET];
+ uint8_t *buf = __buf + AST_FRIENDLY_OFFSET;
+
+ if (chan == NULL)
+ {
+ ast_log(LOG_WARNING, "Fax transmit channel is NULL. Giving up.\n");
+ return -1;
+ }
+
+ span_set_message_handler(span_message);
+
+ /* The next few lines of code parse out the filename and header from the input string */
+ if (data == NULL)
+ {
+ /* No data implies no filename or anything is present */
+ ast_log(LOG_WARNING, "Txfax requires an argument (filename)\n");
+ return -1;
+ }
+
+ calling_party = FALSE;
+ verbose = FALSE;
+ source_file[0] = '\0';
+
+ for (option = 0, v = s = data; v; option++, s++)
+ {
+ t = s;
+ v = strchr(s, '|');
+ s = (v) ? v : s + strlen(s);
+ strncpy((char *) buf, t, s - t);
+ buf[s - t] = '\0';
+ if (option == 0)
+ {
+ /* The first option is always the file name */
+ len = s - t;
+ if (len > 255)
+ len = 255;
+ strncpy(source_file, t, len);
+ source_file[len] = '\0';
+ }
+ else if (strncmp("caller", t, s - t) == 0)
+ {
+ calling_party = TRUE;
+ }
+ else if (strncmp("debug", t, s - t) == 0)
+ {
+ verbose = TRUE;
+ }
+ }
+
+ /* Done parsing */
+
+ u = ast_module_user_add(chan);
+
+ if (chan->_state != AST_STATE_UP)
+ {
+ /* Shouldn't need this, but checking to see if channel is already answered
+ * Theoretically asterisk should already have answered before running the app */
+ res = ast_answer(chan);
+ }
+
+ if (!res)
+ {
+ original_read_fmt = chan->readformat;
+ if (original_read_fmt != AST_FORMAT_SLINEAR)
+ {
+ res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
+ if (res < 0)
+ {
+ ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
+ return -1;
+ }
+ }
+ original_write_fmt = chan->writeformat;
+ if (original_write_fmt != AST_FORMAT_SLINEAR)
+ {
+ res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
+ if (res < 0)
+ {
+ ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
+ res = ast_set_read_format(chan, original_read_fmt);
+ if (res)
+ ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
+ return -1;
+ }
+ }
+ fax_init(&fax, calling_party);
+ if (verbose)
+ fax.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
+
+ x = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
+ if (x && x[0])
+ t30_set_local_ident(&fax.t30_state, x);
+ x = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO");
+ if (x && x[0])
+ t30_set_header_info(&fax.t30_state, x);
+ t30_set_tx_file(&fax.t30_state, source_file, -1, -1);
+ //t30_set_phase_b_handler(&fax.t30_state, phase_b_handler, chan);
+ //t30_set_phase_d_handler(&fax.t30_state, phase_d_handler, chan);
+ t30_set_phase_e_handler(&fax.t30_state, phase_e_handler, chan);
+ t30_set_ecm_capability(&fax.t30_state, TRUE);
+ t30_set_supported_compressions(&fax.t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
+ while (ast_waitfor(chan, -1) > -1)
+ {
+ inf = ast_read(chan);
+ if (inf == NULL)
+ {
+ res = -1;
+ break;
+ }
+ if (inf->frametype == AST_FRAME_VOICE)
+ {
+ if (fax_rx(&fax, inf->data, inf->samples))
+ break;
+ samples = (inf->samples <= MAX_BLOCK_SIZE) ? inf->samples : MAX_BLOCK_SIZE;
+ len = fax_tx(&fax, (int16_t *) &buf[AST_FRIENDLY_OFFSET], samples);
+ if (len)
+ {
+ memset(&outf, 0, sizeof(outf));
+ outf.frametype = AST_FRAME_VOICE;
+ outf.subclass = AST_FORMAT_SLINEAR;
+ outf.datalen = len*sizeof(int16_t);
+ outf.samples = len;
+ outf.data = &buf[AST_FRIENDLY_OFFSET];
+ outf.offset = AST_FRIENDLY_OFFSET;
+ if (ast_write(chan, &outf) < 0)
+ {
+ ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno));
+ break;
+ }
+ }
+ }
+ ast_frfree(inf);
+ }
+ if (inf == NULL)
+ {
+ ast_log(LOG_DEBUG, "Got hangup\n");
+ res = -1;
+ }
+ if (original_read_fmt != AST_FORMAT_SLINEAR)
+ {
+ res = ast_set_read_format(chan, original_read_fmt);
+ if (res)
+ ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
+ }
+ if (original_write_fmt != AST_FORMAT_SLINEAR)
+ {
+ res = ast_set_write_format(chan, original_write_fmt);
+ if (res)
+ ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", chan->name);
+ }
+ t30_terminate(&fax.t30_state);
+ }
+ else
+ {
+ ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
+ }
+ ast_module_user_remove(u);
+ return res;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int unload_module(void)
+{
+ int res;
+
+ ast_module_user_hangup_all();
+
+ res = ast_unregister_application(app);
+
+
+ return res;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int load_module(void)
+{
+ return ast_register_application(app, txfax_exec, synopsis, descrip);
+}
+/*- End of function --------------------------------------------------------*/
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Trivial FAX Transmit Application");
+
+/*- End of file ------------------------------------------------------------*/
diff -Nru asterisk-1.4.22.org/build_tools/menuselect-deps.in asterisk-1.4.22/build_tools/menuselect-deps.in
--- asterisk-1.4.22.org/build_tools/menuselect-deps.in 2008-08-14 04:02:15.000000000 +0200
+++ asterisk-1.4.22/build_tools/menuselect-deps.in 2008-11-29 15:02:27.000000000 +0100
@@ -23,6 +23,7 @@
POPT=@PBX_POPT@
PRI=@PBX_PRI@
RADIUS=@PBX_RADIUS@
+SPANDSP=@PBX_SPANDSP@
SPEEX=@PBX_SPEEX@
SPEEXDSP=@PBX_SPEEXDSP@
SPEEX_PREPROCESS=@PBX_SPEEX_PREPROCESS@
diff -Nru asterisk-1.4.22.org/configure.ac asterisk-1.4.22/configure.ac
--- asterisk-1.4.22.org/configure.ac 2008-09-08 18:26:00.000000000 +0200
+++ asterisk-1.4.22/configure.ac 2008-11-29 15:02:27.000000000 +0100
@@ -201,6 +201,7 @@
AST_EXT_LIB_SETUP([PWLIB], [PWlib], [pwlib])
AST_EXT_LIB_SETUP([OPENH323], [OpenH323], [h323])
AST_EXT_LIB_SETUP([RADIUS], [Radius Client], [radius])
+AST_EXT_LIB_SETUP([SPANDSP], [spandsp Library], [spandsp])
AST_EXT_LIB_SETUP([SPEEX], [Speex], [speex])
AST_EXT_LIB_SETUP([SPEEXDSP], [Speexdsp], [speexdsp])
AST_EXT_LIB_SETUP([SQLITE], [SQLite], [sqlite])
@@ -1302,6 +1303,8 @@
AST_EXT_LIB_CHECK([RADIUS], [radiusclient-ng], [rc_read_config], [radiusclient-ng.h])
+AST_EXT_LIB_CHECK([SPANDSP], [spandsp], [fax_init], [spandsp.h], [-ltiff -ljpeg -lz])
+
AST_EXT_LIB_CHECK([SPEEX], [speex], [speex_encode], [speex/speex.h], [-lm])
# See if the main speex library contains the preprocess functions
diff -Nru asterisk-1.4.22.org/include/asterisk/plc.h asterisk-1.4.22/include/asterisk/plc.h
--- asterisk-1.4.22.org/include/asterisk/plc.h 2006-06-14 16:12:56.000000000 +0200
+++ asterisk-1.4.22/include/asterisk/plc.h 2008-11-29 15:02:27.000000000 +0100
@@ -1,18 +1,17 @@
-/*! \file
- * \brief SpanDSP - a series of DSP components for telephony
+/*
+ * SpanDSP - a series of DSP components for telephony
*
* plc.h
*
- * \author Steve Underwood <steveu@coppice.org>
+ * Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2004 Steve Underwood
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -23,37 +22,36 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * This version may be optionally licenced under the GNU LGPL licence.
- *
- * A license has been granted to Digium (via disclaimer) for the use of
- * this code.
+ * $Id: plc.h,v 1.15 2007/04/08 08:16:18 steveu Exp $
*/
+/*! \file */
-#if !defined(_PLC_H_)
-#define _PLC_H_
-
-#ifdef SOLARIS
-#include <sys/int_types.h>
-#else
-#if defined(__OpenBSD__) || defined( __FreeBSD__)
-#include <inttypes.h>
-#else
-#include <stdint.h>
-#endif
-#endif
+#if !defined(_SPANDSP_PLC_H_)
+#define _SPANDSP_PLC_H_
/*! \page plc_page Packet loss concealment
\section plc_page_sec_1 What does it do?
-The packet loss concealment module provides a suitable synthetic fill-in signal,
-to minimise the audible effect of lost packets in VoIP applications. It is not
-tied to any particular codec, and could be used with almost any codec which does not
+The packet loss concealment module provides a synthetic fill-in signal, to minimise
+the audible effect of lost packets in VoIP applications. It is not tied to any
+particular codec, and could be used with almost any codec which does not
specify its own procedure for packet loss concealment.
-Where a codec specific concealment procedure exists, the algorithm is usually built
+Where a codec specific concealment procedure exists, that algorithm is usually built
around knowledge of the characteristics of the particular codec. It will, therefore,
generally give better results for that particular codec than this generic concealer will.
+The PLC code implements an algorithm similar to the one described in Appendix 1 of G.711.
+However, the G.711 algorithm is optimised for 10ms packets. Few people use such small
+packets. 20ms is a much more common value, and longer packets are also quite common. The
+algorithm has been adjusted with this in mind. Also, the G.711 approach causes an
+algorithmic delay, and requires significant buffer manipulation when there is no packet
+loss. The algorithm used here avoids this. It causes no delay, and achieves comparable
+quality with normal speech.
+
+Note that both this algorithm, and the one in G.711 are optimised for speech. For most kinds
+of music a much slower decay on bursts of lost packets give better results.
+
\section plc_page_sec_2 How does it work?
While good packets are being received, the plc_rx() routine keeps a record of the trailing
section of the known speech signal. If a packet is missed, plc_fillin() is called to produce
@@ -83,7 +81,7 @@
correct steadily fall. Therefore, the volume of the synthesized signal is made to decay
linearly, such that after 50ms of missing audio it is reduced to silence.
-- When real speech resumes, an extra 1/4 pitch period of sythetic speech is blended with the
+- When real speech resumes, an extra 1/4 pitch period of synthetic speech is blended with the
start of the real speech. If the erasure is small, this smoothes the transition. If the erasure
is long, and the synthetic signal has faded to zero, the blending softens the start up of the
real signal, avoiding a kind of "click" or "pop" effect that might occur with a sudden onset.
@@ -110,6 +108,9 @@
the pitch assessment. */
#define PLC_HISTORY_LEN (CORRELATION_SPAN + PLC_PITCH_MIN)
+/*!
+ The generic packet loss concealer context.
+*/
typedef struct
{
/*! Consecutive erased samples */
@@ -127,12 +128,13 @@
} plc_state_t;
-#ifdef __cplusplus
-extern "C" {
+#if defined(__cplusplus)
+extern "C"
+{
#endif
-/*! Process a block of received audio samples.
- \brief Process a block of received audio samples.
+/*! Process a block of received audio samples for PLC.
+ \brief Process a block of received audio samples for PLC.
\param s The packet loss concealer context.
\param amp The audio sample buffer.
\param len The number of samples in the buffer.
@@ -147,13 +149,18 @@
\return The number of samples synthesized. */
int plc_fillin(plc_state_t *s, int16_t amp[], int len);
-/*! Process a block of received V.29 modem audio samples.
- \brief Process a block of received V.29 modem audio samples.
+/*! Initialise a packet loss concealer context.
+ \brief Initialise a PLC context.
\param s The packet loss concealer context.
- \return A pointer to the he packet loss concealer context. */
+ \return A pointer to the the packet loss concealer context. */
plc_state_t *plc_init(plc_state_t *s);
-#ifdef __cplusplus
+/*! Free a packet loss concealer context.
+ \param s The packet loss concealer context.
+ \return 0 for OK. */
+int plc_release(plc_state_t *s);
+
+#if defined(__cplusplus)
}
#endif
diff -Nru asterisk-1.4.22.org/makeopts.in asterisk-1.4.22/makeopts.in
--- asterisk-1.4.22.org/makeopts.in 2008-06-12 21:08:20.000000000 +0200
+++ asterisk-1.4.22/makeopts.in 2008-11-29 15:02:27.000000000 +0100
@@ -138,6 +138,9 @@
RADIUS_INCLUDE=@RADIUS_INCLUDE@
RADIUS_LIB=@RADIUS_LIB@
+SPANDSP_INCLUDE=@SPANDSP_INCLUDE@
+SPANDSP_LIB=@SPANDSP_LIB@
+
SPEEX_INCLUDE=@SPEEX_INCLUDE@
SPEEX_LIB=@SPEEX_LIB@

View file

@ -0,0 +1,12 @@
diff -Nru asterisk-1.4.22.org/configure.ac asterisk-1.4.22/configure.ac
--- asterisk-1.4.22.org/configure.ac 2008-09-08 18:26:00.000000000 +0200
+++ asterisk-1.4.22/configure.ac 2008-11-29 15:04:09.000000000 +0100
@@ -514,7 +514,7 @@
fi
fi
-AST_EXT_LIB_CHECK([IKSEMEL], [iksemel], [iks_start_sasl], [iksemel.h])
+AST_EXT_LIB_CHECK([IKSEMEL], [iksemel], [iks_start_sasl], [iksemel.h], [-lgnutls -lgcrypt -lgpg-error])
if test "${PBX_IKSEMEL}" = 1; then
AST_EXT_LIB_CHECK([GNUTLS], [gnutls], [gnutls_bye], [gnutls/gnutls.h], [-lz -lgcrypt -lgpg-error])

View file

@ -0,0 +1,12 @@
diff -Nru asterisk-1.4.22.org/Makefile asterisk-1.4.22/Makefile
--- asterisk-1.4.22.org/Makefile 2008-09-08 22:15:42.000000000 +0200
+++ asterisk-1.4.22/Makefile 2008-11-29 15:05:12.000000000 +0100
@@ -215,7 +215,7 @@
endif
ifneq ($(PROC),ultrasparc)
- ASTCFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi)
+ #ASTCFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi)
endif
ifeq ($(PROC),ppc)

View file

@ -0,0 +1,23 @@
diff -Nru asterisk-1.4.22.org/acinclude.m4 asterisk-1.4.22/acinclude.m4
--- asterisk-1.4.22.org/acinclude.m4 2008-07-22 22:49:41.000000000 +0200
+++ asterisk-1.4.22/acinclude.m4 2008-11-29 15:06:28.000000000 +0100
@@ -588,6 +588,7 @@
;;
esac
AC_MSG_RESULT(${OPENH323_BUILD})
+ OPENH323_SUFFIX="n_s"
AC_SUBST([OPENH323_SUFFIX])
AC_SUBST([OPENH323_BUILD])
diff -Nru asterisk-1.4.22.org/configure.ac asterisk-1.4.22/configure.ac
--- asterisk-1.4.22.org/configure.ac 2008-09-08 18:26:00.000000000 +0200
+++ asterisk-1.4.22/configure.ac 2008-11-29 15:06:28.000000000 +0100
@@ -1259,7 +1259,7 @@
if test "${HAS_PWLIB:-unset}" != "unset"; then
AST_CHECK_OPENH323_PLATFORM()
- PLATFORM_PWLIB="pt_${PWLIB_PLATFORM}_r"
+ PLATFORM_PWLIB="pt_${PWLIB_PLATFORM}_r_s"
AST_CHECK_PWLIB_BUILD([PWLib], [PWLIB],
[Define if your system has the PWLib libraries.],

View file

@ -0,0 +1,41 @@
diff -Nru asterisk-1.4.22.org/acinclude.m4 asterisk-1.4.22/acinclude.m4
--- asterisk-1.4.22.org/acinclude.m4 2008-07-22 22:49:41.000000000 +0200
+++ asterisk-1.4.22/acinclude.m4 2008-11-29 15:08:07.000000000 +0100
@@ -664,7 +664,7 @@
[assume the C compiler uses GNU ld @<:@default=no@:>@])],
[test "$withval" = no || with_gnu_ld=yes],
[with_gnu_ld=no])
-AC_REQUIRE([AST_PROG_SED])dnl
+AC_REQUIRE([AC_PROG_SED])dnl
AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([AC_CANONICAL_HOST])dnl
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
@@ -769,28 +769,6 @@
AC_SUBST([EGREP])
])]) # AST_PROG_EGREP
-# AST_PROG_SED
-# -----------
-# Check for a fully functional sed program that truncates
-# as few characters as possible. Prefer GNU sed if found.
-AC_DEFUN([AST_PROG_SED],
-[AC_CACHE_CHECK([for a sed that does not truncate output], ac_cv_path_SED,
- [dnl ac_script should not contain more than 99 commands (for HP-UX sed),
- dnl but more than about 7000 bytes, to catch a limit in Solaris 8 /usr/ucb/sed.
- ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
- for ac_i in 1 2 3 4 5 6 7; do
- ac_script="$ac_script$as_nl$ac_script"
- done
- echo "$ac_script" | sed 99q >conftest.sed
- $as_unset ac_script || ac_script=
- _AC_PATH_PROG_FEATURE_CHECK(SED, [sed gsed],
- [_AC_FEATURE_CHECK_LENGTH([ac_path_SED], [ac_cv_path_SED],
- ["$ac_path_SED" -f conftest.sed])])])
- SED="$ac_cv_path_SED"
- AC_SUBST([SED])dnl
- rm -f conftest.sed
-])# AST_PROG_SED
-
dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
dnl
dnl @summary figure out how to build C programs using POSIX threads

View file

@ -0,0 +1,42 @@
diff -Nru asterisk-1.4.22.org/main/asterisk.c asterisk-1.4.22/main/asterisk.c
--- asterisk-1.4.22.org/main/asterisk.c 2008-07-26 17:31:21.000000000 +0200
+++ asterisk-1.4.22/main/asterisk.c 2008-12-20 22:49:58.000000000 +0100
@@ -2935,7 +2935,38 @@
#if HAVE_WORKING_FORK
if (ast_opt_always_fork || !ast_opt_no_fork) {
#ifndef HAVE_SBIN_LAUNCHD
+#ifndef __UCLIBC__
daemon(1, 0);
+#else
+/*
+ workaround for uClibc-0.9.29 mipsel bug:
+ recursive mutexes do not work if uClibc daemon() function has been called,
+ if parent thread locks a mutex
+ the child thread cannot acquire a lock with the same name
+ (same code works if daemon() is not called)
+ but duplication of uClibc daemon.c code in here does work.
+*/
+ int fd;
+ switch (fork()) {
+ case -1:
+ exit(1);
+ case 0:
+ break;
+ default:
+ _exit(0);
+ }
+ if (setsid() == -1)
+ exit(1);
+ if (fork())
+ _exit(0);
+ if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
+ dup2(fd, STDIN_FILENO);
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
+ if (fd > 2)
+ close(fd);
+ }
+#endif
ast_mainpid = getpid();
/* Blindly re-write pid file since we are forking */
unlink(ast_config_AST_PID);