openwrt / telephony

The telephony packages feed
102 stars 230 forks source link

Asterisk: Time to remove the "flash filling" config clutter and move it to uci #369

Open LipkeGu opened 5 years ago

LipkeGu commented 5 years ago

Since a long time we have the problem that asterisk is very unfriendly to configure. It contains a lot of config files which are mostly full commented out.

i decided to write a uci file togehter with an init script to make it easier and flash friendlier. my way is to move "our" generated config files into /tmp/asterisk/ instead of overwriting the /etc/ this allows us a first step to make configs upgrade persistent.

In fact we cant cover all situations but generate a starting base to make asterisk more useable for embedded devices.

config asterisk
    option verbose          '0'
    option dontwarn     'yes'
    option maxcalls         '2'
    option maxload          '0.9'
    option minmemfree       '1'
    option tansmit_silence  'yes'
    option language     'de'
    option systemname       '10.21.0.1'
    option autosystemname   'yes'
    option mindtmfduration  '80'

# modules
    option autoload     'yes'

# user
    option userbase     '6000'

# sip
    option port         '5060'
    option bindaddr     '0.0.0.0'
    option context          'default'
    option srvlookup        'yes'
    option nat          'yes'
    option allowguest       'no'
    option transport        'udp'
    list networks           '10.21.0.0/255.255.255.0'
    list networks           '10.22.0.0/255.255.255.0'
    list networks           '10.30.0.0/255.255.255.0'
    list networks           '10.40.0.0/255.255.255.0'

# rtp
    option rtpstart         '15000'
    option rtpend           '30000'
    option dnsmgr           'yes'
    option refreshinterval  '1200'

config asterisk_user
    option fullname     'Lipke'
    option description      'Linksys'
    option email            'lipkegu@fblipke.de'
    option secret           '1234'
    option vmsecret     '1234'
    option hasvoicemail     'no'
    option hassip           'yes'
    option hasiax           'no'
    option hash323      'no'
    option hasmanager       'no'
    option callwaiting      'no'
    option macaddress       '000E083B586F'
    option autoprov     'yes'
    option linekeys         '1'
    option linenumber       '1'
    option cidnumber        '6000'
    option treewaycalling   'yes'
    option callwaitingcallerid  'yes'
    option transfer         'yes'
    option canpark          'yes'
    option cancallforward   'yes'
    option callreturn       'yes'
    option callgroup        '1'
    option pickupgroup      '1'

config asterisk_register
    option defaultuser      '##########'
    option password     '##########'
    option domain           'sipgate.de'

config asterisk_peer
    option number           '6000'
    option type         'friend'
    option secret           '1234'
    option host         'dynamic'
    option qualify          'yes'
    option description      'IP Device'
    option context          'default'

config asterisk_peer
    option number           'sipgate'
    option context          'sipgate-in'
    option type         'peer'
    option secret           '########'
    option host         'sipgate.de'
    option canreinvite      'no'
    option fromdomain       'sipgate.de'
    option defaultuser      '########'
    option fromuser     '########'
    option insecure         'port,invite'
    option dtmfmode     'rfc2833'
    option disallow         'all'
    option allow            'alaw&ulaw'
    option outboundproxy    'sipgate.de'

config asterisk_dialplan
    option context      '_default'
    option pattern      '_[0-9].'
    list entries            '1,Answer()'
    list entries            '2,Hangup()'

config asterisk_dialplan
    option context      'internal'
    option pattern      '_01.'
    list entries            '1,Answer()'
    list entries            '2,Playback(pls-hold-while-try&one-moment-please)'
    list entries            '3,Wait(1)'
    list entries            '4,Dial(SIP/${EXTEN:2},30)'
    list entries            '5,Playback(number-not-answering&please-try-call-later,noanswer)'
    list entries            '6,Wait(1)'
    list entries            '7,Hangup()'

config asterisk_dialplan
    option context      'sipgate-out'
    option pattern      '_02.'
    option source       'exten'
    list entries            '1,Answer()'
    list entries            '2,Playback(pls-hold-while-try&one-moment-please)'
    list entries            '3,Wait(1)'
    list entries            '4,Dial(SIP/${EXTEN:2}@sipgate,30)'
    list entries            '5,Playback(number-not-answering&please-try-call-later,noanswer)'
    list entries            '6,Wait(1)'
    list entries            '7,Hangup()'

config asterisk_dialplan
    option context      'sipgate-in'
    option pattern      '########'
    option source       'exten'
    list entries            '1,Answer()'
    list entries            '2,Playback(pls-hold-while-try&one-moment-please)'
    list entries            '3,Wait(1)'
    list entries            '4,Dial(SIP/6000,30)'
    list entries            '5,Playback(number-not-answering&please-try-call-later,noanswer)'
    list entries            '6,Wait(1)'
    list entries            '7,Hangup()'

/etc/init.d/asterisk contains so far:

#!/bin/sh /etc/rc.common
# Copyright (C) 2018 OpenWrt.org

START=99
APP=asterisk
OPTIONS=
DEST=
DEFAULT=$DEST/etc/default/$APP
BIN_FILE=$DEST/usr/sbin/$APP
PID_FILE=$DEST/var/run/$APP/$APP.pid

# creates the config files and its general settings...

asterisk_set_header() {
    local verbose
    local dontwarn
    local maxcalls
    local maxload
    local minmemfree
    local transmit_silence
    local language
    local systemname
    local autosystemname
    local mindtmfduration
    local autoload

    # user template
    local userbase

    # sip
    local port
    local bindaddr
    local context
    local srvlookup
    local nat
    local allowguest
    local networks

    # rtp
    local rtpstart
    local rtpend

    # dnsmgr
    local dnsmgr
    local refreshinterval

    # main
    config_get verbose $1 verbose
    config_get dontwarn $1 dontwarn
    config_get maxcalls $1 maxcalls
    config_get maxload $1 maxload
    config_get minmemfree $1 minmemfree
    config_get transmit_silence $1 transmit_silence
    config_get language $1 language
    config_get systemname $1 systemname
    config_get autosystemname $1 autosystemname
    config_get mindtmfduration $1 mindtmfduration

    # modules
    config_get autoload $1 autoload

    # user template
    config_get userbase $1 userbase

    # sip
    config_get port $1 port
    config_get allowguest $1 allowguest
    config_get transport $1 transport
    config_get networks $1 networks
    config_get bindaddr $1 bindaddr
    config_get context $1 context
    config_get srvlookup $1 srvlookup
    config_get nat $1 nat

    # rtp
    config_get rtpstart $1 rtpstart
    config_get rtpend $1 rtpend

    # dns
    config_get dnsmgr $1 dnsmgr
    config_get refreshinterval $1 refreshinterval

    echo -e "[directories](!)\n
    astetcdir => /tmp/asterisk
    astmoddir => /usr/lib/asterisk/modules
    astvarlibdir => /usr/lib/asterisk
    astdbdir => /usr/lib/asterisk
    astkeydir => /usr/lib/asterisk
    astdatadir => /usr/lib/asterisk
    astagidir => /usr/lib/asterisk/agi-bin
    astspooldir => /var/spool/asterisk
    astrundir => /var/run/asterisk
    astlogdir => /var/log/asterisk
    astsbindir => /usr/sbin" > /etc/asterisk/asterisk.conf

    mkdir -p /tmp/asterisk/
    echo -e "[options]" >> /tmp/asterisk/asterisk.conf
    [ -n "$verbose" ] && echo -e "verbose=$verbose" >> /tmp/asterisk/asterisk.conf
    [ -n "$dontwarn" ] && echo -e "dontwarn=$dontwarn" >> /tmp/asterisk/asterisk.conf
    [ -n "$maxcalls" ] && echo -e "maxcalls=$maxcalls" >> /tmp/asterisk/asterisk.conf
    [ -n "$maxload" ] && echo -e "maxload=$maxload" >> /tmp/asterisk/asterisk.conf
    [ -n "$minmemfree" ] && echo -e "minmemfree=$minmemfree" >> /tmp/asterisk/asterisk.conf
    [ -n "$transmit_silence" ] && echo -e "transmit_silence=$transmit_silence" >> /tmp/asterisk/asterisk.conf
    [ -n "$language" ] && echo -e "language=$language" >> /tmp/asterisk/asterisk.conf
    [ -n "$systemname" ] && echo -e "systemname=$systemname" >> /tmp/asterisk/asterisk.conf
    [ -n "$autosystemname" ] && echo -e "autosystemname=$autosystemname" >> /tmp/asterisk/asterisk.conf
    [ -n "$mindtmfduration" ] && echo -e "mindtmfduration=$mindtmfduration" >> /tmp/asterisk/asterisk.conf

    # modules (autoload by default....)
    echo -e "[modules]" > /tmp/asterisk/modules.conf
    echo -e "autoload = yes" >> /tmp/asterisk/modules.conf

    # user template
    echo -e "[general]" > /tmp/asterisk/users.conf
    [ -n "$userbase" ] && echo -e "userbase = $userbase" >> /tmp/asterisk/users.conf

    # sip
    echo -e "[general]" > /tmp/asterisk/sip.conf
    [ -n "$port" ] && echo -e "port = $port" >> /tmp/asterisk/sip.conf
    [ -n "$allowguest" ] && echo -e "allowguest = $allowguest" >> /tmp/asterisk/sip.conf
    [ -n "$transport" ] && echo -e "transport = $transport" >> /tmp/asterisk/sip.conf
    [ -n "$bindaddr" ] && echo -e "bindaddr = $bindaddr" >> /tmp/asterisk/sip.conf
    [ -n "$context" ] && echo -e "context = $context" >> /tmp/asterisk/sip.conf
    [ -n "$srvlookup" ] && echo -e "srvlookup = $srvlookup" >> /tmp/asterisk/sip.conf

    for network in $networks; do
        [ -n "$network" ] && echo -e "localnet = $network" >> /tmp/asterisk/sip.conf
    done

    # rtp
    echo -e "[general]" > /tmp/asterisk/rtp.conf
    [ -n "$rtpstart" ] && echo -e "rtpstart = $rtpstart" >> /tmp/asterisk/rtp.conf
    [ -n "$rtpend" ] && echo -e "rtpend = $rtpend" >> /tmp/asterisk/rtp.conf

    # dns
    echo -e "[general]" > /tmp/asterisk/dnsmgr.conf
    [ -n "$dnsmgr" ] && echo -e "enabled = $dnsmgr" >> /tmp/asterisk/dnsmgr.conf
    [ -n "$refreshinterval" ] && echo -e "refreshinterval = $refreshinterval" >> /tmp/asterisk/dnsmgr.conf

    echo -e "[general]" > /tmp/asterisk/extensions.conf
}

asterisk_adduser() {
    local fullname
    local description
    local email
    local secret
    local vmsecret
    local dahdichan
    local hasvoicemail
    local hassip
    local hasiax
    local hash323
    local hasmanager
    local callwaiting
    local context
    local alternateexts
    local macaddress
    local autoprov
    local linekeys
    local linenumber
    local cidnumber
    local treewaycalling
    local callwaitingcallerid
    local transfer
    local canpark
    local cancallforward
    local callreturn
    local callgroup
    local pickupgroup

    config_get fullname $1 fullname
    config_get description $1 description
    config_get email $1 email
    config_get secret $1 secret
    config_get vmsecret $1 vmsecret
    config_get dahdichan $1 dahdichan
    config_get hasvoicemail $1 hasvoicemail
    config_get hassip $1 hassip
    config_get hasiax $1 hasiax
    config_get hasmanager $1 hasmanager
    config_get callwaiting $1 callwaiting
    config_get context $1 context
    config_get alternateexts $1 alternateexts
    config_get macaddress $1 macaddress
    config_get autoprov $1 autoprov
    config_get linekeys $1 linekeys
    config_get linenumber $1 linenumber
    config_get cidnumber $1 cidnumber
    config_get threewaycalling $1 threewaycalling
    config_get callwaitingcallerid $1 callwaitingcallerid
    config_get transfer $1 transfer
    config_get canpark $1 canpark
    config_get cancallforward $1 cancallforward
    config_get callreturn $1 callreturn
    config_get callgroup $1 callgroup
    config_get pickupgroup $1 pickupgroup

    echo -e "\n[$cidnumber]" >> /tmp/asterisk/users.conf
    [ -n "$fullname" ] && echo -e "fullname = $fullname" >> /tmp/asterisk/users.conf
    [ -n "$description" ] && echo -e "description = $description" >> /tmp/asterisk/users.conf
    [ -n "$email" ] && echo -e "email = $email" >> /tmp/asterisk/users.conf
    [ -n "$secret" ] && echo -e "secret = $secret" >> /tmp/asterisk/users.conf
    [ -n "$vmsecret" ] && echo -e "vmsecret = $vmsecret" >> /tmp/asterisk/users.conf
    [ -n "$dahdichan" ] && echo -e "dahdichan = $dahdichan" >> /tmp/asterisk/users.conf
    [ -n "$hasvoicemail" ] && echo -e "hasvoicemail = $hasvoicemail" >> /tmp/asterisk/users.conf
    [ -n "$hassip" ] && echo -e "hassip = $hassip" >> /tmp/asterisk/users.conf
    [ -n "$hasiax" ] && echo -e "hasiax = $hasiax" >> /tmp/asterisk/users.conf
    [ -n "$hash323" ] && echo -e "hash323 = $hash323" >> /tmp/asterisk/users.conf
    [ -n "$hasmanager" ] && echo -e "hasmanager = $hasmanager" >> /tmp/asterisk/users.conf
    [ -n "$callwaiting" ] && echo -e "callwaiting = $callwaiting" >> /tmp/asterisk/users.conf
    [ -n "$context" ] && echo -e "context = $context" >> /tmp/asterisk/users.conf
    [ -n "$alternateexts" ] && echo -e "alternateexts = $alternateexts" >> /tmp/asterisk/users.conf
    [ -n "$macaddress" ] && echo -e "macaddress = $macaddress" >> /tmp/asterisk/users.conf
    [ -n "$autoprov" ] && echo -e "autoprov = $autoprov" >> /tmp/asterisk/users.conf
    [ -n "$linekeys" ] && echo -e "linekeys = $linekeys" >> /tmp/asterisk/users.conf
    [ -n "$linenumber" ] && echo -e "linenumber = $linenumber" >> /tmp/asterisk/users.conf
    [ -n "$cidnumber" ] && echo -e "cidnumber = $cidnumber" >> /tmp/asterisk/users.conf
    [ -n "$threewaycalling" ] && echo -e "threewaycalling = $threewaycalling" >> /tmp/asterisk/users.conf
    [ -n "$callwaitingcallerid" ] && echo -e "callwaitingcallerid = $callwaitingcallerid" >> /tmp/asterisk/users.conf
    [ -n "$transfer" ] && echo -e "transfer = $transfer" >> /tmp/asterisk/users.conf
    [ -n "$canpark" ] && echo -e "canpark = $canpark" >> /tmp/asterisk/users.conf
    [ -n "$cancallforward" ] && echo -e "cancallforward = $cancallforward" >> /tmp/asterisk/users.conf
    [ -n "$callreturn" ] && echo -e "callreturn = $callreturn" >> /tmp/asterisk/users.conf
    [ -n "$callgroup" ] && echo -e "callgroup = $callgroup" >> /tmp/asterisk/users.conf
    [ -n "$pickupgroup" ] && echo -e "pickupgroup = $pickupgroup" >> /tmp/asterisk/users.conf
}

# creates the peer sections...
asterisk_addpeer() {
    local number
    local type
    local host
    local fromuser
    local defaultuser
    local secret
    local fromdomain
    local context
    local canreinvite
    local qualify
    local insecure
    local dtmfmode
    local disallow
    local outboundproxy

    config_get number $1 number
    config_get type $1 type
    config_get host $1 host
    config_get fromuser $1 fromuser
    config_get defaultuser $1 defaultuser
    config_get secret $1 secret
    config_get fromdomain $1 fromdomain
    config_get context $1 context
    config_get canreinvite $1 canreinvite
    config_get qualify $1 qualify
    config_get insecure $1 insecure
    config_get dtmfmode $1 dtmfmode
    config_get disallow $1 disallow
    config_get allow $1 allow
    config_get outboundproxy $1 outboundproxy
    config_get transport $1 transport

    [ -n "$number" ] && echo -e "\n[$number]" >> /tmp/asterisk/sip.conf
    [ -n "$type" ] && echo -e "type = $type" >> /tmp/asterisk/sip.conf
    [ -n "$host" ] && echo -e "host = $host" >> /tmp/asterisk/sip.conf
    [ -n "$fromuser" ] && echo -e "fromuser = $fromuser" >> /tmp/asterisk/sip.conf
    [ -n "$defaultuser" ] && echo -e "defaultuser = $defaultuser" >> /tmp/asterisk/sip.conf
    [ -n "$secret" ] && echo -e "secret = $secret" >> /tmp/asterisk/sip.conf
    [ -n "$fromdomain" ] && echo -e "fromdomain = $fromdomain" >> /tmp/asterisk/sip.conf
    [ -n "$context" ] && echo -e "context = $context" >> /tmp/asterisk/sip.conf
    [ -n "$canreinvite" ] && echo -e "canreinvite = $canreinvite" >> /tmp/asterisk/sip.conf
    [ -n "$qualify" ] && echo -e "qualify = $qualify" >> /tmp/asterisk/sip.conf
    [ -n "$insecure" ] && echo -e "insecure = $insecure" >> /tmp/asterisk/sip.conf
    [ -n "$dtmfmode" ] && echo -e "dtmfmode = $dtmfmode" >> /tmp/asterisk/sip.conf
    [ -n "$disallow" ] && echo -e "disallow = $disallow" >> /tmp/asterisk/sip.conf
    [ -n "$allow" ] && echo -e "allow = $allow" >> /tmp/asterisk/sip.conf
    [ -n "$outboundproxy" ] && echo -e "outboundproxy = $outboundproxy" >> /tmp/asterisk/sip.conf
    [ -n "$transport" ] && echo -e "transport = $transport" >> /tmp/asterisk/sip.conf
}

# writes out the "register" lines in sip.cond -> comes from the equaling uci section
asterisk_dialplan() {
    local context
    local pattern
    local entries
    local preincludes
    local postincludes

    config_get context $1 context
    config_get pattern $1 pattern
    config_get entries $1 entries
    config_get preincludes $1 preincludes
    config_get postincludes $1 postincludes

    [ -n "$context" ] && echo -e "[$context]" >> /tmp/asterisk/extensions.conf
    for include in $preincludes; do
        [ -n "$context" ] && echo -e "include => $include" >> /tmp/asterisk/extensions.conf
    done

    for entrie in $entries; do
        [ -n "$context" ] && echo -e "exten => $pattern,$entrie" >> /tmp/asterisk/extensions.conf
    done

    for include in $postincludes; do
        [ -n "$context" ] && echo -e "include => $include" >> /tmp/asterisk/extensions.conf
    done

    [ -n "$context" ] && echo -e "" >> /tmp/asterisk/extensions.conf
}

asterisk_register() {
    local defaultuser
    local password
    local domain
    local prefix

    config_get defaultuser $1 defaultuser
    config_get password $1 password
    config_get domain $1 domain 
    config_get prefix $1 prefix 

    [ -n "$defaultuser" ] && echo -e "register => $defaultuser$prefix:$password@$domain/$defaultuser" >> /tmp/asterisk/sip.conf
}

start() {
    config_load asterisk
    config_foreach asterisk_set_header asterisk
    config_foreach asterisk_register asterisk_register
    config_foreach asterisk_adduser asterisk_user
    config_foreach asterisk_addpeer asterisk_peer

    config_foreach asterisk_dialplan asterisk_dialplan

    [ -f $DEFAULT ] && . $DEFAULT
    [ -d $DEST/var/run/asterisk ] || mkdir -p $DEST/var/run/asterisk
    [ -d $DEST/var/log/asterisk ] || mkdir -p $DEST/var/log/asterisk
    [ -d $DEST/var/spool/asterisk ] || mkdir -p $DEST/var/spool/asterisk
    [ -d $DEST/var/lib ] || mkdir -p $DEST/var/lib
    [ -h $DEST/var/lib/asterisk ] || ln -s /usr/lib/asterisk /var/lib/asterisk
    [ -d $DEST/var/lib/asterisk/keys ] || mkdir -p $DEST/var/lib/asterisk/keys
    [ -d $DEST/var/log/asterisk/cdr-csv ] || mkdir -p $DEST/var/log/asterisk/cdr-csv
    [ -d $DEST/var/lib/asterisk/moh ] || mkdir -p $DEST/var/lib/asterisk/moh

    SERVICE_PID_FILE="/var/run/asterisk/asterisk.pid" \
    service_start $BIN_FILE $OPTIONS
}

stop() {
    SERVICE_PID_FILE="/var/run/asterisk/asterisk.pid" \
    service_stop $BIN_FILE
}

reload() {
    SERVICE_PID_FILE="/var/run/asterisk/asterisk.pid" \
    service_reload $BIN_FILE
}

Im currently using it and it makes (except the dialplan patterns) the life of my box alot easier... Any suggestions?

LipkeGu commented 5 years ago

Update 1:

update 2

jslachta commented 5 years ago

Hi @LipkeGu,

I like the idea of transforming config to uci. However I miss the possibility of configuring modules that your provided uci config does not handle. Have you thought about it?

dkgroot commented 5 years ago

@LipkeGu Have you considered using asterisk-realtime + sqlite3 instead. Most of the asterisk config can be moved to a database (odbc, mysql, postgresql, sqlite3 and/or ldap). For example sippeers / iaxpeers / voicemail / sccp / queues / musiconhold / meetme / confbridge and even dialplan (there are some caveats with extensions.conf though). That should/would get rid of a lot of the clutter and might make a nice frontend simpler. See:

Note:You would have to make sure to retain this sqlite3 db over openwrt upgrades though. Also note: setting up realtime can be a little bit daunting though (getting extconfig.conf + res_sqlite.conf right the first time). but once it is up and running it works really well and reduces the need for "module reload [all]" in a lot of cases.

When you are going to use files: do note that almost all asterisk config files parameters have sensible defaults don't have to be defined, which can reduce the size of files considerably.