Anda di halaman 1dari 77

PENDAHULUAN

1
1.1 Pengertian VOIP.

VoIP (Voice over Internet Protocol) merupakan nama lain internet telephony.
Internet telephony adalah hardware dan software yang memungkinkan
pengguna Internet untuk media transmisi panggilan telepon. Kualitas Internet
telephony ini belum sebaik kualitas koneksi telepon langsung. Voice over
Internet Protocol (VoIP) adalah teknologi yang mampu melewatkan trafik
suara, video dan data yang berbentuk paket melalui jaringan IP.
Dalam komunikasi VoIP, pemakai melakukan hubungan telepon melalui
terminal yang berupa PC atau telepon. Terminal akan berkomunikasi dengan
gateway melalui telefoni lokal. Hubungan antar gateway dilakukan melalui
network IP.
Network IP dapat berupa network paket apapun, termasuk ATM, FR, Internet,
Intranet, atau line E1. VoIP menawarkan transportasi sinyal yang lebih murah,
feature tambahan, dan transparansi terhadap data komputer. Hambatan VoIP
saat ini adalah kehandalannya yang di bawah telefoni biasa, dan soal
standarisasi yang akan menyangkut masalah interoperabilitas.

1.2 KEUNTUNGAN MENGGUNAKAN VOIP

Dengan bertelepon menggunakan VoIP, banyak keuntungan yang dapat


diambil. Diantaranya adalah dari segi biaya, jelas lebih murah dari tarif
telepon tradisional, karena jaringan IP bersifat global sehingga untuk
hubungan Internasional dapat ditekan hingga 70%. Selain itu, biaya
maintenance dapat di tekan karena voice dan data network terpisah, sehingga
IP Phone dapat ditambah, dipindah dan di ubah. Hal ini karena VoIP dapat
dipasang di sembarang ethernet dan IP address, tidak seperti telepon
tradisional yang harus mempunyai port tersendiri di Sentral atau PBX.

2
1.3 KELEMAHAN VOIP

• Sulit mengirimkan fax


• Perlu jalur internet yang cepat, biasanya backbone diharuskan
menggunakan Fiber optic
• Susah untuk menentukan emergency call.

Kelemahan jaringan yang menjadi musuh VoIP :


1. Delay
Jaringan yang berbasis atau dengan backbone Satellite tidak cocok
untuk VoIP. Karena delay satellite yang sangat besar. Sehingga
menyebabkan suara kita lama didengar oleh lawan bicara.
Solusi : Backbone fiber optic.
2. Jitter
Jitter pada intinya adalah variasi dalam delay, terjadi karena adanya
perubahan terhadap karakteristik dari suatu sinyal sehingga
menyebabkan terjadinya masalah terhadap data yang dibawa oleh sinyal
tersebut. Solusinya : Mengaplikasikan suatu sistem buffer pada pesawat
penerima untuk menstabilkan data suara sebelum ditampilkan. Efek
sampingnya akan ada sedikit delay.
3. Packet Loss
Paket loss artinya hilangnya paket data yang sedang dikirimkan.
Hilangnya data ini bisa disebabkan karena Jitter atau karena adanya
permasalahan di perangkat-perangakat jaringan seperti router yang
terlalu sibuk, jalur komunikasi yang terlalu padat penggunanya.
Solusi : Peralatan yang lebih bagus dibandingkan peralatan jaringan
untuk internet biasa, kualitas koneksi yang lebih baik dan perhitungan
terhadap penggunaan bandwidth yang lebih baik.
4. Keamanan
Karena suara berjalan pada jaringan internet maka tetap akan ada
kemungkinan data suara tersebut disadap oleh pihak-pihak yang tidak
bertanggung jawab.
Solusi : Membangun sistem keamanan yang lebih baik, enkripsi data.
5. Echo
Echo atau gema disebabkan oleh kesalahan perangkat pengirim dan
penerima suara dalam mengconversikan atau mengubah data dari suara
menjadi digital atau sebaliknya biasanya karena adanya kesalahan
faktor impedansi dalam rangkaian analog peralatan.
Solusi : Melengkapi peralatan dengan rangkaian analog coupling yang
bisa meredam kesalahan faktor impedansi.

3
1.4 CARA KERJA VOIP
Hal yang menarik tentang VoIP adalah banyaknya cara untuk melakukan
panggilan. Saat ini ada 3 jenis metode yg berbeda yang paling sering
digunakan untuk melakukan layalan VoIP, yaitu :

1. ATA (Analog Telephone Adaptor)


Cara yang paling sederhana dan paling umum adalah dengan
menggunakan suatu alat yang disebut ATA. ATA memungkinkan kita
untuk menghubungkan pesawat telepon biasa ke komputer atau
disambungkan ke internet untuk dipakai VoIP. ATA adalah alat
pengubah sinyal dari analog menjadi digital. Cara kerjanya adalah
mengubah sinyal analog dari telepon dan mengubahnya menjadi data
digital untuk di transmisikan melalui internet. Provider seperti VONAGE
dan AT&T Callvantage membuat alat ATA dan memberikannya secara
gratis kepada pelanggannya sebagai bagian dari service mereka. Mereka
tinggal membuka ATA, memasang kabel telepon ke alat, dan VoIP sudah
bisa digunakan. Beberapa jenis ATA dipaket dan dibundel beserta
software tambahan yang harus diinstalkan pada komputer untuk
melakukan konfigurasi ATA, tetapi pada umumnya itu hanya setting
yang sangat gampang.

2. IP Phones
Pesawat telepon khusus ini kelihatannya sama dengan telepon biasa.
Tapi selain mempunyai konektor RJ-11 standar, IP Phones juga
mempunyai konektor RJ-45. IP Phones menghubungkan langsung dari
telepon ke router, dan didalam IP Phones sudah ada semua perangkat
keras maupun lunak yang sudah terpasang didalamnya yang
menunjang melakukan pemanggilan IP. Tidak lama lagi, IP Phone
nirkabel (wireless) akan tersedia, dan memungkinkan para pengguna
untuk melakukan panggilan VoIP dari hotspot yang tersedia.

3. Computer-to-Computer
Cara ini jelas merupakan cara paling mudah untuk melakukan
panggilan VoIP. Anda bahkan tidak usah membayar satu sen pun untuk
melakukan panggilan SLJJ. Ada beberapa perusahaan yang
menawarkan program yang harganya murah bahkan gratis yang dapat
digunakan untuk melakukan panggilan VoIP. Yang harus anda sediakan
hanya program (software), mikrofon, speaker, soundcard dan koneksi
internet, lebih diutamakan koneksi internet yang relatif cepat seperti
koneksi Kabel atau DSL. Selain biaya bulanan ISP, biasanya tidak ada
lagi biaya untuk panggilan Computer-to-Computer, seberapa jauh pun
jaraknya.

4
1.5 Protokol Penunjang Jaringan VoIP
Ada beberapa protokol yang menjadi penunjang jaringan VoIP, antara lain :

1. Protokol TCP/IPTCP/IP (Transfer Control Protocol/Internet Protocol)


merupakan sebuah protokol yang digunakan pada jaringan Internet.
Protokol ini terdiri dari dua bagian besar, yaitu TCP dan IP.

2. Application layer
Fungsi utama lapisan ini adalah pemindahan file. Perpindahan file dari
sebuah sistem ke sistem lainnya yang berbeda memerlukan suatu
sistem pengendalian untuk menangatasi adanya ketidak cocokan sistem
file yang berbeda beda. Protokol ini berhubungan dengan aplikasi.
Salah satu contoh aplikasi yang telah dikenal misalnya HTTP (Hypertext
Transfer Protocol) untuk web, FTP(File Transfer Protocol) untuk
perpindahan file, dan TELNET untuk terminal maya jarak jauh.

3. TCP (Transmission Control Protocol)


Dalam mentransmisikan data pada layer Transpor ada dua protokol
yang berperan yaitu TCP danUDP. TCP merupakan protokol yang
connection-oriented yang artinya menjaga reliabilitas hubungan
komunikadasi end-to-end. Konsep dasar cara kerja TCP adalah mengirm
dan menerima segmen segmen informasi dengan panjang data
bervariasi pada suatu datagram internet. TCP menjamin realibilitas
hubungan komunikasi karena melakukan perbaikan terhadap data yang
rusak, hilang atau kesalahan kirim. Hal ini dilakukan dengan
memberikan nomor urut pada setiap paket yang dikirimkan dan
membutuhkan sinyal jawaban positif dari penerima berupa sinyal
ACK(acknoledgment). Jika sinyal ACK ini tidak diterima pada interval
pada waktu tertentu, maka data akan dikirikmkan kembali. Pada sisi
penerima, nomor urut tadi berguna untuk mencegah kesalahan urutan
data dan duplikasi data. TCP juga memiliki mekanisme fllow control
dengan cara mencantumkan informasi dalam sinyal ACK mengenai
batas jumlah paket data yang masih boleh ditransmisikan pada setiap
segmen yang diterima dengan sukses. Dalam hubungan VoIP, TCP
digunakan pada saat signaling, TCP digunakan untuk menjamin setup
suatu call pada sesi signaling. TCP tidak digunakan dalam pengiriman
data suara pada VoIP karena pada suatu komunikasi data VoIP
penanganan data yang mengalami keterlambatan lebih penting daripada
penanganan paket yang hilang.

4. User Datagram Protocol (UDP)


UDP yang merupakan salah satu protocol utama diatas IP merupakan
transport protocol yang lebih sederhana dibandingkan dengan TCP. UDP
digunakan untuk situasi yang tidak mementingkan mekanisme
reliabilitas. Header UDP hanya berisi empat field yaitu source port,
destination port, length dan UDP checksum dimana fungsinya hampir
5
sama dengan TCP, namun fasilitas checksumpada UDP bersifat
opsional.UDP pada VoIP digunakan untuk mengirimkan audio stream
yang dikrimkan secara terus menerus.UDP digunakan pada VoIP karena
pada pengiriman audio streaming yang berlangsung terusmenerus lebih
mementingkan kecepatan pengiriman data agar tiba di tujuan tanpa
memperhatikan adanya paket yang hilang walaupun mencapai 50% dari
jumlah paket yang dikirimkan. (VoIP fundamental, Davidson Peters,
Cisco System,163 ) Karena UDP mampu mengirimkan data streaming
dengan cepat, maka dalam teknologi VoIP UDPmerupakan salah satu
protokol penting yang digunakan sebagai header pada pengiriman data
selainRTP dan IP. Untuk mengurangi jumlah paket yang hilang saat
pengiriman data (karena tidakterdapat mekanisme pengiriman ulang)
maka pada teknolgi VoIP pengiriman data banyak dilakukan pada
private network.

5. Internet Protocol (IP)


Internet Protocol didesain untuk interkoneksi sistem komunikasi
komputer pada jaringan paket switched.Pada jaringan TCP/IP, sebuah
komputer diidentifikasi dengan alamat IP. Tiap-tiapkomputer memiliki
alamat IP yang unik, masing-masing berbeda satu sama lainnya. Hal ini
dilakukan untuk mencegah kesalahan pada transfer data. Terakhir,
protokol data akses berhubungan langsung dengan media fisik. Secara
umum protokol ini bertugas untuk menangani pendeteksiankesalahan
pada saat transfer data. Untuk komunikasi datanya, Internet Protokol
mengimplementasikan dua fungsi dasar yaitu addressing dan
fragmentasi. Salah satu hal penting dalam IP dalam pengiriman
informasi adalah metode pengalamatan pengirimdan penerima. Saat ini
terdapat standar pengalamatan yang sudah digunakan yaitu IPv4
denganalamat terdiri dari 32 bit. Jumlah alamat yang diciptakan dengan
IPv4 diperkirakan tidak dapatmencukupi kebutuhan pengalamatan IP
sehingga dalam beberapa tahun mendatang akan diimplementasikan
sistim pengalamatan yang baru yaitu IPv6 yang menggunakan sistim
pengalamatan 128 bit.

1.6 REGULASI

VoIP berkembang karena adanya persaingan yang bebas dan dukungan


pemerintah, setidaknya inilah yang terjadi di Amerika. Monopoli perusahaan
besar dihindari (misalnya monopoli AT&T diakhiri pada tahun 1984) dan
pengawasan ketat pada persaingan yang sehat (misalnya saat dua internet
backbone service provider terbesar, MCI dan WorldCom merger pada tahun
1998, pemerintah tetap berusaha agar tidak ada perusahaan yang
mendominasi dengan mewajibkan internet backbone mereka dipakai oleh
perusahaan kompetitor).

6
Persaingan menyebabkan setiap perusahaan berusaha menghasilkan
inovasi/produk baru. Karena adanya resiko investasi, pemerintah AS turut
membantu dengan mengurangi pajak guna membantu inovasi dan memacu
potensial market dengan mensupport perusahaan pengembang teknologi (The
National Institute for Standards and Technology, National Institues of Health,
National Oceanic and Atmospheric Administration, dan the National Science
Foundation).

FCC sebagai salah satu lembaga yang berkompeten mengusulkan traditional


charge pada layanan yang secara langsung bersaing dengan traditional
company. FCC membedakan layanan voice melalui komputer (enhanced
service yang dianggap tidak masuk dalam access charges dan regulasi lain)
atau voice melalui handset telpon standar yang mendial melalui gateway IP
(dianggap sebagai telepone tradisional dengan long-distance access charges).

Perkembangan VoIP dipengaruhi faktor ekonomi, regulasi dan teknologi.


Regulasi pemerintah sering sekali menjadi interferensi. Pemerintah mencoba
me-micromanage kompetisi yang semakin besar dan terlalu kompleks dengan
powerfull financial interest. Sementara industri telkom semakin less regulated
dan persaingan semakin bebas. Birokrasi, kecemasan dan social justice
dianggap sebagai faktor yang memperlambat proses.

Di Indonesia, Pemerintah (dalam hal ini Dirjen Postel) menganggap


penyelenggara VOIP mengganggu operator resmi. Pelarangan dilakukan
dengan cara penggerebekan meskipun dasar hukumnya tidak kuat. Alasan
pelarangan hanya menyangkut soal izin serta tidak adanya standarisasi
penggunaan peralatan yang harus dikeluarkan Dirjen Postel. Di sisi lain,
sanksi yang dikenakan juga masih terlalu ringan dibanding keuntungan yang
diperoleh.

Menurut Ir. Suryatin Setiawan Direktur divisi Penelitian dan Pengembangan


PT Telkom, VoIP baru bermasalah jika perusahaan penyedianya sudah
bertindak sebagai operator. Suhono Supangat, Multimedia Signal Processing
and Communication Research Group ITB menjelaskan bahwa pelarangan VoIP
tanpa cyberlaw akan membatasi pengembangan aplikasi berbasis IP pada
public network.serta menghambat pembuatan jaringan baru yang mendukung
beragam komunikasi multimedia yang merupakan basis teknologi massa
depan.

Indosat juga mempertimbangkan VoIP untuk SLInya, namun terikat ketentuan


dalam KM 37/1999 yakni Indosat harus membayar biaya interkoneksi kepada
PT Telkom Rp 1.350/menit atau sama dengan US$ 15,5 sen. Peralihan ke
teknologi VoIP tidak akan efektif kecuali ketentuan tersebut diubah.

7
INSTALASI VOIP SERVER UNILA

8
2.1 Instalasi

• Lakukan Instalasi Terlebih System Operasi TRIXBOX terlebih dahulu

• Instalasi dilakukan sama dengan Instalasi pada System Operasi Linux

Lainnya.

• Hardisk akan ter-format otomatis oleh Linux TRIXBOX ini

Catatan :

Backup data anda sebelum instalasi dilakukan

2.2 Konfigurasi IP TRIXBOX

• Setelah Instalasi, Anda harus mengkonfigurasi IP Address dengan cara :

• Ketik netconfig

• Pilih Yes

• Isi IP Address, Netmask, Default Gateway (IP) dan Primary Name server

• Pilih OK

• Kemudian Ketik /etc/init.d/network restart dan enter

untuk me-restart network

9
2.3 Konfigurasi TRIXBOX

• Masuk ke Internet Explorer / Web Browser lainnya

• Ketik IP Address atau hostname TRIXBOX (http://voip.unila.ac.id)

Tampilan Awal Konfigurasi TRIXBOX

10
• Klik System Administration Untuk masuk ke menu System administration

• Isi user dengan maint

• Isi Password dengan wuelektro

• Klik OK untuk melanjutkan

11
2.4 Menu System Administration

• Klik Menu FreePBX untuk masuk ke Menu FreePBX

12
• Klik Menu Tools

• Pertama kali kita harus melakukan instalasi module: Core

13
2.5 Menu Tools

• Klik Module Admin

14
• Beri Tanda centang pada Core (core)

• Pilih Enable Selected dan kemudian Submit

• Klik Menu Setup

15
2.6 Menu Setup

• Klik Menu Extensions

• Pada Menu Add an Extensions

Klik Menu SIP

16
Menu Add SIP Extensions

• Isi Extensions Number : Misal 101

• Isi Display Name : Misal line1

• Isi Secret : Misal 123456

• Kemudian Klik Submit

• Add SIP Extensions digunakan untuk

membuat/menambahkan Client.

• Extensions = User/No VoIP • secret = Password

17
• Klik You have made changes-when finished, click here to APPLY them

Untuk menyimpan hasil perubahan.

18
2.7 Peering ke voiprakyat.or.id

• Klik Menu Trunks

• Klik Menu Add SIP Trunk

• Trunk Name : Isikan voiprakyat.or.id

• Host = Voiprakyat.or.id

• username = voiprakyat.or.id

• Secret= Password

• Register String :

(Username : password@voiprakyat.or.id)

• Klik Submit Changes untuk

menyelesaikan konfigurasi

19
• Klik You have made changes-when finished, click here to

APPLY them Untuk menyimpan hasil perubahan.

Klik Outbound Routes

• Route Name: Isikan voiprakyat.or.id

• Dial Patterns Isi misal 6|x.

• Trunk Squence Pilih SIP/voiprakyat.or.id

• Klik Add untuk menambahkan

Outbound Routes

20
• Klik You have made changes-when finished, click here to APPLY

them Untuk menyimpan hasil perubahan.

KETERANGAN

• Extensions

• Merupakan data account extensions (atau client)

• Trunks

• Merupakan data account trunks (atau server lain)

• Outbound Routes

• Merupakan aturan dial yang akan dimanfaatkan oleh

extensions untuk menghubungi trunks

21
2.8 Konfigurasi interkoneksi VOIP server dengan PABX Siemens UNILA.

1. Matikan Power server, pasang card Digium AX-100p

1 FXO pada slot PCI.

2. Masuk ke console CLI TRIXBOX

[ root@voip.unila ~]# genzaptelconf

TRIXBOX akan secara otomatis mengenali dan menginstall driver


AX-100p

status pada monitor akan menampilkan warning berikut

Loading wcfxo: wcfxo: DAA mode is “FCC”

Found a Wildcard FXO: Wildcard X100P.

Yang menandakan bahwa Voip server telah berhasil mengenali


hardware.

3. check AX-100p status dengan mengetikkan command line utility

zttool.*

[ root@voip.unila ~]# zttool

commanf Genzaptelconf juga otomatis mengupdate file zapata-auto.conf,

file tersebut ada di direktori /etc/asterisk

22
berikut isi file zapata-auto.conf

; Span 1: WCFXO/0 "Wildcard X100P Board 1" RED

signalling=fxs_ks

; Note: this is a trunk. Create a ZAP trunk in AMP for Channel 1

context=from-pstn

group=0

channel => 1

4. Edit file zapata.conf, dan tambahkan statemen berikut.

echocancel=yes

echocancelwhenbridged=yes

echotraining=yes

5. KOnfigurasi Outbound call trunk dengan memodifikasi default trunk

ZAP/g0

Masuk ke menu Trixbox - FreePBX - Trunk

Masukkan nomer PSTN/PABX pada outbound caller ID (Ekstensi PABX


yang akan digunakan adalah 128)

Set Maximum Channels dengan nilai 1.

Set Outbound Dial Prefix dengan nilai 9

23
Selanjutnya ubah file /etc/zaptel.conf

dengan isian sbb,

loadzone = uk

defaultzone = uk

Updating Server Linux,

masuk ke direktori /usr/src

> cd /usr/src

Download last CVS release dari Zapata driver, asterisk package

> export CVSROOT=:pserver: anoncvs@cvs.digium.com:/usr/cvsroot

> cvs login (password is anoncvs)

> cvs checkout zaptel asterisk

Compile semua packages: zaptel yang pertama, selanjutnya asterisk

> cd /usr/src/zaptel; make install

> cd ../asterisk; make install

> make samples

24
edit beberapa file config berikut

/etc/zaptel.conf

fxsks=1 ;AX-100P

defaultzone=uk

loadzone=uk

/etc/asterisk/zapata.conf

[channels]

signalling=fxs_ks

context=incoming

channel=>1 ; AX-100P

/etc/asterisk/extensions.conf

[incoming]

exten => s,1,Echo ;for testing the connection

;exten => s,1,Playback,demo-thanks ;for playing a file

Untuk mengaktifkan modul yang sudah diinstall, ketikkan command

berikut

> modprobe zaptel

> modprobe wcfxo

> ztcfg -vv

25
Proses instalasi interkoneksi dari VOIP server ke PABX analog telah
selesai ketik command berikut untuk melihat aktifitas di server VOIP

> asterisk -vvvc

Pengujian dilakukan dengan menekan tombol 9 diikuti ekstensi dari


PABX UNILA

26
2.9 Petunjuk penggunaan Softphone Client (X-lite 3.0).

- Download XLite 3.0 untuk aplikasi telepon VoIP.


- Pada menu download XLite for free!, klik XLite
3.0 for windows, jika anda menggunakan sistem operasi windows.

27
28
29
30
31
32
33
34
35
2.10 Lampiran File konfigurasi;

- Asterisk.conf
[directories]
astetcdir => /etc/asterisk
astmoddir => /usr/lib/asterisk/modules
astvarlibdir => /var/lib/asterisk
astagidir => /var/lib/asterisk/agi-bin
astspooldir => /var/spool/asterisk
astrundir => /var/run/asterisk
astlogdir => /var/log/asterisk

[options]
transmit_silence_during_record = yes
; nocolor = yes

- cdr_mysql.conf
;
; Note - if the database server is hosted on the same machine as the
; asterisk server, you can achieve a local Unix socket connection by
; setting hostname=localhost
;
; port and sock are both optional parameters. If hostname is specified
; and is not "localhost", then cdr_mysql will attempt to connect to the
; port specified or use the default port. If hostname is not specified
; or if hostname is "localhost", then cdr_mysql will attempt to connect
; to the socket file specified by sock or otherwise use the default socket
; file.
;
[global]
hostname=localhost
dbname=asteriskcdrdb
password=amp109
user=asteriskuser
;port=3306
;sock=/tmp/mysql.sock

36
- codec.conf

[speex]

; CBR encoding quality [0..10]

; used only when vbr = false

quality => 3

; codec complexity [0..10]

; tradeoff between cpu/quality

complexity => 2

; perceptual enhancement [true / false]

; improves clarity of decoded speech

enhancement => true

; voice activity detection [true / false]

; reduces bitrate when no voice detected, used only for CBR


(implicit in VBR/ABR)

vad => true

; variable bit rate [true / false]

; uses bit rate proportionate to voice complexity

vbr => true

; available bit rate [bps, 0 = off]

; encoding quality modulated to match this target bit rate

; not recommended with dtx or pp_vad - may cause bandwidth


spikes

abr => 0

37
; VBR encoding quality [0-10]

; floating-point values allowed

vbr_quality => 4

; discontinuous transmission [true / false]

; stops transmitting completely when silence is detected

; pp_vad is far more effective but more CPU intensive

dtx => false

; preprocessor configuration

; these options only affect Speex v1.1.8 or newer

; enable preprocessor [true / false]

; allows dsp functionality below but incurs CPU overhead

preprocess => false

; preproc voice activity detection [true / false]

; more advanced equivalent of DTX, based on voice frequencies

pp_vad => false

; preproc automatic gain control [true / false]

pp_agc => false

pp_agc_level => 8000

; preproc denoiser [true / false]

pp_denoise => false

; preproc dereverb [true / false]

pp_dereverb => false

pp_dereverb_decay => 0.4

pp_dereverb_level => 0.3

38
[plc]

; for all codecs which do not support native PLC

; this determines whether to perform generic PLC

; there is a minor performance penalty for this

genericplc => true

- extconfig.conf
;
; Static and realtime external configuration
; engine configuration
;
; Please read doc/README.extconfig for basic table
; formatting information.
;
[settings]
;
; Static configuration files:
;
; file.conf => driver,database[,table]
;
; maps a particular configuration file to the given
; database driver, database and table (or uses the
; name of the file as the table if not specified)
;
;uncomment to load queues.conf via the odbc engine.
;
;queues.conf => odbc,asterisk,ast_config
;
; The following files CANNOT be loaded from Realtime storage:
; asterisk.conf
; extconfig.conf (this file)
; logger.conf
;
; Additionally, the following files cannot be loaded from

39
; Realtime storage unless the storage driver is loaded
; early using 'preload' statements in modules.conf:
; manager.conf
; cdr.conf
; rtp.conf
;
;
; Realtime configuration engine
;
; maps a particular family of realtime
; configuration to a given database driver,
; database and table (or uses the name of
; the family if the table is not specified
;
;example => odbc,asterisk,alttable
;iaxusers => odbc,asterisk
;iaxpeers => mysql,asteriskrealtime,iax_buddies
;sipusers => odbc,asterisk
;sippeers => mysql,asteriskrealtime,sip_buddies
;voicemail => mysql,asteriskrealtime,voicemail_users
;extensions => mysql,asteriskrealtime,extensions
;queues => odbc,asterisk
;queue_members => odbc,asterisk

- extension.conf
; FreePBX
; Copyright (C) 2004 Coalescent Systems Inc (Canada)
; Copyright (C) 2006 Why Pay More 4 Less Pty Ltd (Australia)
; Released under the GNU GPL Licence version 2.

; dialparties.agi (http://www.sprackett.com/asterisk/)
; Asterisk::AGI (http://asterisk.gnuinter.net/)
; gsm
(http://www.ibiblio.org/pub/Linux/utils/compress/!INDEX.short.ht
ml)
; loligo sounds (http://www.loligo.com/asterisk/sounds/)
; mpg123 (http://voip-info.org/wiki-
Asterisk+config+musiconhold.conf)

40
; include extension contexts generated from AMP
#include extensions_additional.conf

; Customizations to this dialplan should be made in


extensions_custom.conf
; See extensions_custom.conf.sample for an example
#include extensions_custom.conf

[from-trunk] ; just an alias


since VoIP shouldn't be called PSTN
include => from-pstn

[from-pstn]
include => from-pstn-custom ; create this context in
extensions_custom.conf to include customizations
include => ext-did-direct ; MODIFICATOIN (PL) put before
ext-did to take precedence
include => ext-did
include => from-did-direct ; MODIFICATOIN (PL) for
findmefollow if enabled, should be bofore ext-local
exten => fax,1,Goto(ext-fax,in_fax,1)

; MODIFICATION (PL)
;
; Required to assure that direct dids go to personal ring group before
local extension.
; This could be auto-generated however I it is prefered to be put here
and hard coded
; so that it can be modified if ext-local should take precedence in
certain situations.
; will have to decide what to do later.
;
[from-did-direct]
include => ext-findmefollow
include => ext-local

41
;
#########################################################
###################
; Macros [macro]
;
#########################################################
###################

; Rings one or more extensions. Handles things like call forwarding


and DND
; We don't call dial directly for anything internal anymore.
; ARGS: $TIMER, $OPTIONS, $EXT1, $EXT2, $EXT3, ...
; Use a Macro call such as the following:
; Macro(dial,$DIAL_TIMER,$DIAL_OPTIONS,$EXT1,$EXT2,$EXT3,...)
[macro-dial]
exten => s,1,DeadAGI(dialparties.agi)
exten => s,2,NoOp(Returned from dialparties with no extensions to
call)
exten => s,3,NoOp(DIALSTATUS is '${DIALSTATUS}')

exten => s,10,Dial(${ds}) ; dialparties will set the


priority to 10 if $ds is not null

exten => s,20,NoOp(Returned from dialparties with hunt groups to


dial )
exten => s,21,Set(HuntLoop=0)
exten => s,22,GotoIf($[${HuntMembers} >= 1]?30 ) ; if this is from rg-
group, don't strip prefix
exten => s,23,NoOp(Returning there are no members left in the hunt
group to ring)

exten => s,30,Set(HuntMember=HuntMember${HuntLoop})


exten => s,31,GotoIf($[$["${CALLTRACE_HUNT}" != "" ] &
$["${RingGroupMethod}" = "hunt" ]]?32:35 ) ; Set CAll Trace for Hunt
member we are going to call
exten => s,32,Set(CT_EXTEN=${CUT(ARG3,,$[${HuntLoop} + 1])})
exten =>
s,33,Set(DB(CALLTRACE/${CT_EXTEN})=${CALLTRACE_HUNT})
exten => s,34,Goto(s,42)

42
exten => s,35,GotoIf($[$["${CALLTRACE_HUNT}" != "" ] &
$["${RingGroupMethod}" = "memoryhunt" ]]?36:50 ) ;Set Call Trace for
each hunt member we are going to call "Memory groups have multiple
members to set CALL TRACE For hence the loop
exten => s,36,Set(CTLoop=0)
exten => s,37,GotoIf($[${CTLoop} > ${HuntLoop}]?42 ) ; if this is from
rg-group, don't strip prefix
exten => s,38,Set(CT_EXTEN=${CUT(ARG3,,$[${CTLoop} + 1])})
exten =>
s,39,Set(DB(CALLTRACE/${CT_EXTEN})=${CALLTRACE_HUNT})
exten => s,40,Set(CTLoop=$[1 + ${CTLoop}])
exten => s,41,Goto(s,37)

exten => s,42,Dial(${${HuntMember}}${ds} ) ; dialparties will set the


priority to 20 if $ds is not null and its a hunt group
exten => s,43,Set(HuntLoop=$[1 + ${HuntLoop}])
exten => s,44,Set(HuntMembers=$[${HuntMembers} - 1])
exten => s,45,Goto(s,22)
exten => s,50,DBdel(CALLTRACE/${CT_EXTEN})
exten => s,51,Goto(s,42)

; make sure hungup calls go here so that proper cleanup occurs from
call confirmed calls and the like
;
exten => h,1,Macro(hangupcall)

; Ring an extension, if the extension is busy or there is no answer


send it
; to voicemail
; ARGS: $VMBOX, $EXT
[macro-exten-vm]
exten => s,1,Macro(user-callerid)

exten => s,n,Set(FROMCONTEXT=exten-vm)


exten => s,n,Set(VMBOX=${ARG1})
exten => s,n,Set(EXTTOCALL=${ARG2})
exten => s,n,Set(CFUEXT=${DB(CFU/${EXTTOCALL})})
exten => s,n,Set(CFBEXT=${DB(CFB/${EXTTOCALL})})
exten => s,n,Set(RT=${IF($[$["${VMBOX}"!="novm"] |
$["foo${CFUEXT}"!="foo"]]?${RINGTIMER}:"")})

43
exten => s,n,Macro(record-enable,${EXTTOCALL},IN)

exten => s,n,Macro(dial,${RT},${DIAL_OPTIONS},${EXTTOCALL})


exten => s,n,GosubIf($[$["${DIALSTATUS}"="NOANSWER"] &
$["foo${CFUEXT}"!="foo"]]?docfu,1) ; check for CFU in use on no
answer
exten => s,n,GosubIf($[$["${DIALSTATUS}"="BUSY"] &
$["foo${CFBEXT}"!="foo"]]?docfb,1) ; check for CFB in use on busy
exten => s,n,NoOp(Voicemail is '${VMBOX}')
exten => s,n,GotoIf($["${VMBOX}" = "novm"]?s-${DIALSTATUS},1) ; no
voicemail in use for this extension
exten => s,n,NoOp(Sending to Voicemail box ${EXTTOCALL})
exten => s,n,Macro(vm,${VMBOX},${DIALSTATUS})

; Try the Call Forward on No Answer / Unavailable number


exten =>
docfu,1,Set(RTCFU=${IF($["${VMBOX}"!="novm"]?${RINGTIMER}:"")})
exten => docfu,n,Dial(Local/${CFUEXT}@from-
internal/n,${RTCFU},${DIAL_OPTIONS})
exten => docfu,n,Return

; Try the Call Forward on Busy number


exten =>
docfb,1,Set(RTCFB=${IF($["${VMBOX}"!="novm"]?${RINGTIMER}:"")})
exten => docfb,n,Dial(Local/${CFBEXT}@from-
internal/n,${RTCFB},${DIAL_OPTIONS})
exten => docfb,n,Return

; Extensions with no Voicemail box reporting BUSY come here


exten => s-BUSY,1,NoOp(Extension is reporting BUSY and not
passing to Voicemail)
exten => s-BUSY,n,Playtones(busy)
exten => s-BUSY,n,Busy(20)

; Anything but BUSY comes here


exten => _s-.,1,Playtones(congestion)
exten => _s-.,n,Congestion(10)

[macro-vm]
exten => s,1,Macro(user-callerid,SKIPTTL)

44
exten =>
s,n,Set(VMGAIN=${IF($["foo${VM_GAIN}"!="foo"]?"g(${VM_GAIN})":"")})
;
; If BLKVM_OVERRIDE is set, then someone told us to block calls
from going to
; voicemail. This variable is reset by the answering channel so
subsequent
; transfers will properly function.
;
exten => s,n,GotoIf($["foo${DB(${BLKVM_OVERRIDE})}" !=
"fooTRUE"]?s-${ARG2},1)
;
; we didn't branch so block this from voicemail
;
exten => s,n,Noop(CAME FROM: ${NODEST} - Blocking VM cause of
key: ${DB(BLKVM_OVERRIDE)})

exten => s-BUSY,1,NoOp(BUSY voicemail)


exten => s-BUSY,n,Macro(get-vmcontext,${ARG1})
exten => s-
BUSY,n,Voicemail(${ARG1}@${VMCONTEXT}|${VM_OPTS}b${VMGAIN}
) ; Voicemail Busy message
exten => s-BUSY,n,Goto(exit-${VMSTATUS},1)

exten => s-DIRECTDIAL,1,NoOp(DIRECTDIAL voicemail)


exten => s-DIRECTDIAL,n,Macro(get-vmcontext,${ARG1})
exten => s-
DIRECTDIAL,n,Voicemail(${ARG1}@${VMCONTEXT}|${VM_OPTS}${VM
_DDTYPE}${VMGAIN})
exten => s-DIRECTDIAL,n,Goto(exit-${VMSTATUS},1)

exten => _s-.,1,Macro(get-vmcontext,${ARG1})


exten => _s-
.,n,Voicemail(${ARG1}@${VMCONTEXT}|${VM_OPTS}u${VMGAIN}) ;
Voicemail Unavailable message
exten => _s-.,n,Goto(exit-${VMSTATUS},1)

exten => o,1,Background(one-moment-please) ; 0 during vm


message will hangup

45
exten => o,n,GotoIf($["x${OPERATOR_XTN}"="x"]?nooper:from-
internal,${OPERATOR_XTN},1)
exten => o,n(nooper),GotoIf($["x${FROM_DID}"="x"]?nodid)
exten => o,n,Dial(Local/${FROM_DID}@from-pstn)
exten => o,n,Macro(hangup)
exten => o,n(nodid),Dial(Local/s@from-pstn)
exten => o,n,Macro(hangup)

exten => a,1,Macro(get-vmcontext,${ARG1})


exten => a,n,VoiceMailMain(${ARG1}@${VMCONTEXT})
exten => a,n,Hangup

exten => exit-FAILED,1,Playback(im-sorry&an-error-has-occured)


exten => exit-FAILED,n,Hangup()

exten => exit-SUCCESS,1,Playback(goodbye)


exten => exit-SUCCESS,n,Hangup()

exten => exit-USEREXIT,1,Playback(goodbye)


exten => exit-USEREXIT,n,Hangup()

exten => t,1,Hangup()

;------------------------------------------------------------------------
; [macro-simple-dial]
;------------------------------------------------------------------------
; This macro was derived from macro-exten-vm, which is what is
normally used to
; ring an extension. It has been simplified and designed to never go to
voicemail
; and always return regardless of the DIALSTATUS for any incomplete
call.
;
; It's current primary purpose is to allow findmefollow ring an
extension prior
; to trying the follow-me ringgroup that is provided.
;
; Ring an extension, if the extension is busy or there is no answer,
return
; ARGS: $EXTENSION, $RINGTIME

46
;------------------------------------------------------------------------
[macro-simple-dial]
exten => s,1,Macro(user-callerid,SKIPTTL) ; already called from follow-
me

; FROMCONTEXT was in the original macro-exten-vm where this


macro was derived from. A
; search through all the modules does not come up with any place
using this
; variable, but it is left here as a reminder in case there is
functionality
; that eventually behaves in a certain way as a result of this variable
being set
; and this macro has to masquerade as exten-vm.
;
exten => s,n,Set(EXTTOCALL=${ARG1})
exten => s,n,Set(RT=${ARG2})
exten => s,n,Set(CFUEXT=${DB(CFU/${EXTTOCALL})})
exten => s,n,Set(CFBEXT=${DB(CFB/${EXTTOCALL})})
exten => s,n,Macro(record-enable,${EXTTOCALL},IN)

exten => s,n,Macro(dial,${RT},${DIAL_OPTIONS},${EXTTOCALL})

exten => s,n,Set(PR_DIALSTATUS=${DIALSTATUS})

; if we return, thus no answer, and they have a CFU setting, then we


try that next
;
exten => s,n,GosubIf($[$["${DIALSTATUS}"="NOANSWER"] &
$["foo${CFUEXT}"!="foo"]]?docfu,1) ; check for CFU in use on no
answer
exten => s,n,GosubIf($[$["${DIALSTATUS}"="BUSY"] &
$["foo${CFBEXT}"!="foo"]]?docfb,1) ; check for CFB in use on busy

; Nothing yet, then go to the end (which will just return, but in case
we decide to do something with certain
; return situations, this is left in.
;
exten => s,n,Goto(s-${DIALSTATUS},1)

47
; Try the Call Forward on No Answer / Unavailable number.
; We want to try CFU if set, but we want the same ring timer as was
set to our call (or do we want the
; system ringtimer? - probably not). Then if no answer there
(assuming it doesn't drop into their vm or
; something we return, which will have the net effect of returning to
the followme setup.)
;
; want to avoid going to other follow-me settings here. So check if the
CFUEXT is a user and if it is
; then direct it straight to ext-local (to avoid getting intercepted by
findmefollow) otherwise send it
; to from-internal since it may be an outside line.
;
exten => docfu,1,GotoIf( $[ "foo${DB(AMPUSER/${CFUEXT}/device)}" =
"foo" ]?chlocal)
exten => docfu,n,Dial(Local/${CFUEXT}@ext-
local,${RT},${DIAL_OPTIONS})
exten => docfu,n,Return
exten => docfu,n(chlocal),Dial(Local/${CFUEXT}@from-
internal/n,${RT},${DIAL_OPTIONS})
exten => docfu,n,Return

; Try the Call Forward on Busy number


exten => docfb,1,GotoIf( $[ "foo${DB(AMPUSER/${CFBEXT}/device)}" =
"foo" ]?chlocal)
exten => docfb,n,Dial(Local/${CFBEXT}@ext-
local,${RT},${DIAL_OPTIONS})
exten => docfb,n,Return
exten => docfb,n(chlocal),Dial(Local/${CFBEXT}@from-
internal/n,${RT},${DIAL_OPTIONS})
exten => docfb,n,Return

; In all cases of no connection, come here and simply return, since the
calling dialplan will
; decide what to do next
exten => _s-.,1,NoOp(Extension is reporting ${EXTEN})
;------------------------------------------------------------------------

48
; get the voicemail context for the user in ARG1
[macro-get-vmcontext]
exten => s,1,Set(VMCONTEXT=${DB(AMPUSER/${ARG1}/voicemail)})
exten => s,2,GotoIf($["foo${VMCONTEXT}" = "foo"]?200:300)
exten => s,200,Set(VMCONTEXT=default)
exten => s,300,NoOp()

; For some reason, if I don't run setCIDname, CALLERID(name) will be


blank in my AGI
; ARGS: none
[macro-fixcid]
exten => s,1,Set(CALLERID(name)=${CALLERID(name)})

; Ring groups of phones


; ARGS: comma separated extension list
; 1 - Ring Group Strategy
; 2 - ringtimer
; 3 - prefix
; 4 - extension list
[macro-rg-group]
exten => s,1,Macro(user-callerid,SKIPTTL) ; already called from
ringgroup
exten => s,2,GotoIf($["${CALLERID(name):0:${LEN(${RGPREFIX})}}" !=
"${RGPREFIX}"]?4:3) ; check for old prefix
exten =>
s,3,Set(CALLERID(name)=${CALLERID(name):${LEN(${RGPREFIX})}}) ;
strip off old prefix
exten => s,4,Set(RGPREFIX=${ARG3}) ; set new prefix
exten => s,5,Set(CALLERID(name)=${RGPREFIX}${CALLERID(name)})
; add prefix to callerid name
exten => s,6,Set(RecordMethod=Group) ; set new prefix
exten => s,7,Macro(record-enable,${MACRO_EXTEN},${RecordMethod})
exten => s,8,Set(RingGroupMethod=${ARG1}) ;
exten => s,9,Macro(dial,${ARG2},${DIAL_OPTIONS},${ARG4})
exten => s,10,Set(RingGroupMethod='') ;

;
; Outgoing channel(s) are busy ... inform the client

49
; but use noanswer features like ringgroups don't break by being
answered
; just to play the message.
;
[macro-outisbusy]
exten => s,1,Playback(all-circuits-busy-now,noanswer)
exten => s,n,Playback(pls-try-call-later,noanswer)
exten => s,n,Macro(hangupcall)

; What to do on hangup.
[macro-hangupcall]
exten => s,1,ResetCDR(w)
exten => s,n,NoCDR()

; Cleanup any remaining RG flag


;
exten => s,n,GotoIf($[ "foo${USE_CONFIRMATION}" = "foo" |
"foo${RINGGROUP_INDEX}" = "foo" | "${CHANNEL}" !=
"${UNIQCHAN}"]?skiprg)
exten => s,n,Noop(Cleaning Up Confirmation Flag:
RG/${RINGGROUP_INDEX}/${CHANNEL})
exten => s,n,DBDel(RG/${RINGGROUP_INDEX}/${CHANNEL})

; Cleanup any remaining BLKVM flag


;
exten => s,n(skiprg),GotoIf($[ "foo${BLKVM_BASE}" = "foo" |
"BLKVM/${BLKVM_BASE}/${CHANNEL}" != "${BLKVM_OVERRIDE}"
]?theend)
exten => s,n,Noop(Cleaning Up Block VM Flag: ${BLKVM_OVERRIDE})
exten => s,n,DBDel(${BLKVM_OVERRIDE})

exten => s,n(theend),Wait(5)


exten => s,n,Hangup

[macro-faxreceive]
exten => s,1,Set(FAXFILE=/var/spool/asterisk/fax/${UNIQUEID}.tif)
exten => s,2,Set(EMAILADDR=${FAX_RX_EMAIL})
exten => s,3,rxfax(${FAXFILE})
exten => s,103,Set(EMAILADDR=${FAX_RX_EMAIL})
exten => s,104,Goto(3)

50
; dialout and strip the prefix
[macro-dialout]
exten => s,1,Macro(user-callerid,SKIPTTL)
exten => s,2,GotoIf($["${ECID${CALLERID(number)}}" = ""]?5)
;check for CID override for exten
exten => s,3,Set(CALLERID(all)=${ECID${CALLERID(number)}})
exten => s,4,Goto(7)
exten => s,5,GotoIf($["${OUTCID_${ARG1}}" = ""]?7) ;check for
CID override for trunk
exten => s,6,Set(CALLERID(all)=${OUTCID_${ARG1}})
exten => s,7,Set(length=${LEN(${DIAL_OUT_${ARG1}})})
exten => s,8,Dial(${OUT_${ARG1}}/${ARG2:${length}})
exten => s,9,Playtones(congestion)
exten => s,10,Congestion(5)
exten => s,109,Macro(outisbusy)

; dialout using default OUT trunk - no prefix


[macro-dialout-default]
exten => s,1,Macro(user-callerid,SKIPTTL)
exten => s,2,Macro(record-enable,${CALLERID(number)},OUT)
exten => s,3,Macro(outbound-callerid,${ARG1})
exten => s,4,Dial(${OUT}/${ARG1})
exten => s,5,Playtones(congestion)
exten => s,6,Congestion(5)
exten => s,105,Macro(outisbusy)

; dialout using a trunk, using pattern matching (don't strip any prefix)
; arg1 = trunk number, arg2 = number, arg3 = route password
;
; MODIFIED (PL)
;
; Modified both Dial() commands to include the new TRUNK_OPTIONS
from the general
; screen of AMP
;
[macro-dialout-trunk]
exten => s,1,Set(DIAL_TRUNK=${ARG1})

51
; If NODEST is set, clear it. No point in remembering since dialout-
trunk will just end in the
; bit bucket. But if answered by an outside line with transfer
capability, we want NODEST to be
; clear so a subsequent transfer to an internal extension works and
goes to voicmail or other
; destinations.
;
exten => s,n,Set(_NODEST=)

exten => s,n,Set(DIAL_NUMBER=${ARG2})


exten => s,n,Set(ROUTE_PASSWD=${ARG3})
exten => s,n,Set(DIAL_TRUNK_OPTIONS=${DIAL_OPTIONS}) // will be
reset to TRUNK_OPTIONS if not intra-company
exten => s,n,GotoIf($["${ROUTE_PASSWD}" = ""]?noauth) ; arg3 is
pattern password
exten => s,n(auth),Authenticate(${ROUTE_PASSWD})
exten => s,n(noauth),Set(GROUP()=OUT_${DIAL_TRUNK})
exten => s,n,Macro(user-callerid,SKIPTTL)
exten => s,n,Macro(record-enable,${CALLERID(number)},OUT)
exten => s,n,GotoIf($["${INTRACOMPANYROUTE}" =
"YES"]?skipoutcid) ;Set to YES if treated like internal
exten => s,n,Set(DIAL_TRUNK_OPTIONS=${TRUNK_OPTIONS})
exten => s,n,Macro(outbound-callerid,${DIAL_TRUNK})
exten =>
s,n(skipoutcid),GotoIf($["${OUTMAXCHANS_${DIAL_TRUNK}}foo" =
"foo"]?nomax)
exten => s,n(checkmax),GotoIf($[ ${GROUP_COUNT()} >
${OUTMAXCHANS_${DIAL_TRUNK}} ]?chanfull)
exten => s,n(nomax),DeadAGI(fixlocalprefix) ; this sets DIAL_NUMBER
to the proper dial string for this trunk
exten =>
s,n,Set(OUTNUM=${OUTPREFIX_${DIAL_TRUNK}}${DIAL_NUMBER}) ;
OUTNUM is the final dial number
exten => s,n,Set(custom=${CUT(OUT_${DIAL_TRUNK},:,1)}) ; Custom
trunks are prefixed with "AMP:"
exten => s,n,GotoIf($["${custom}" = "AMP"]?customtrunk)
exten =>
s,n,Dial(${OUT_${DIAL_TRUNK}}/${OUTNUM},300,${DIAL_TRUNK_OP
TIONS}) ; Regular Trunk Dial

52
exten => s,n,Goto(s-${DIALSTATUS},1)
exten =>
s,n(customtrunk),Set(pre_num=${CUT(OUT_${DIAL_TRUNK},$,1)})
exten => s,n,Set(the_num=${CUT(OUT_${DIAL_TRUNK},$,2)}) ; this is
where we expect to find string OUTNUM
exten => s,n,Set(post_num=${CUT(OUT_${DIAL_TRUNK},$,3)})
exten => s,n,GotoIf($["${the_num}" =
"OUTNUM"]?outnum:skipoutnum) ; if we didn't find "OUTNUM", then
skip to Dial
exten => s,n(outnum),Set(the_num=${OUTNUM}) ; replace "OUTNUM"
with the actual number to dial
exten =>
s,n(skipoutnum),Dial(${pre_num:4}${the_num}${post_num},300,${DIA
L_TRUNK_OPTIONS})
exten => s,n,Goto(s-${DIALSTATUS},1)

exten => s,n(chanfull),Noop(max channels used up)

exten => s-BUSY,1,NoOp(Dial failed due to trunk reporting BUSY -


giving up)
exten => s-BUSY,2,Busy(20)

exten => s-NOANSWER,1,NoOp(Dial failed due to trunk reporting


NOANSWER - giving up)
exten => s-NOANSWER,2,Playtones(congestion)
exten => s-NOANSWER,3,Congestion(20)

exten => s-CANCEL,1,NoOp(Dial failed due to trunk reporting


CANCEL - giving up)
exten => s-CANCEL,2,Playtones(congestion)
exten => s-CANCEL,3,Congestion(20)

exten => _s-.,1,NoOp(Dial failed due to ${DIALSTATUS} - failing


through to other trunks)

exten => h,1,Macro(hangupcall)

; Adds a dynamic agent/member to a Queue


; Prompts for call-back number - in not entered, uses CIDNum
[macro-agent-add]

53
exten => s,1,Wait(1)
exten => s,2,Macro(user-callerid,SKIPTTL)
exten => s,3,Read(CALLBACKNUM,agent-user) ; get callback
number from user
exten => s,4,GotoIf($["${CALLBACKNUM}" = ""]?5:7) ; if user just
pressed # or timed out, use cidnum
exten => s,5,Set(CALLBACKNUM=${CALLERID(number)})
exten => s,6,GotoIf($["${CALLBACKNUM}" = ""]?2) ; if still no
number, start over
exten => s,7,GotoIf($["${ARG2}" = ""]?9:8) ; arg2 is queue
password
exten => s,8,Authenticate(${ARG2})
exten =>
s,9,AddQueueMember(${ARG1}|Local/${CALLBACKNUM}@from-
internal/n) ; using chan_local allows us to have agents over
trunks
exten => s,10,UserEvent(Agentlogin|Agent: ${CALLBACKNUM})
exten => s,11,Wait(1)
exten => s,12,Playback(agent-loginok)
exten => s,13,Hangup()

; Removes a dynamic agent/member from a Queue


; Prompts for call-back number - in not entered, uses CIDNum
[macro-agent-del]
exten => s,1,Wait(1)
exten => s,2,Macro(user-callerid,SKIPTTL)
exten => s,3,Read(CALLBACKNUM,agent-user) ; get callback
number from user
exten => s,4,GotoIf($["${CALLBACKNUM}" = ""]?5:7) ; if user just
pressed # or timed out, use cidnum
exten => s,5,Set(CALLBACKNUM=${CALLERID(number)})
exten => s,6,GotoIf($["${CALLBACKNUM}" = ""]?2) ; if still no
number, start over
exten =>
s,7,RemoveQueueMember(${ARG1}|Local/${CALLBACKNUM}@from-
internal/n)
exten => s,8,UserEvent(RefreshQueue)
exten => s,9,Wait(1)
exten => s,10,Playback(agent-loggedoff)
exten => s,11,Hangup()

54
; arg1 = trunk number, arg2 = number
[macro-dialout-enum]
; This has been violently beaten upon by Rob Thomas,
xrobau@gmail.com
; to 1: Be compliant with all the depreciated bits in asterisk 1.2 and
; above, and 2: to give a good shot at attempting to be compliant with
; RFC3761 by honouring the order in which records are returned.
exten => s,1,GotoIf($["${ARG3}" != ""]?PASSWD:NOPASSWD); arg3 is
pattern password
exten => s,n(PASSWD),Authenticate(${ARG3})
exten => s,n(NOPASSWD),Macro(user-callerid,SKIPTTL)
exten => s,n,Macro(record-enable,${CALLERID(number)},OUT)
exten => s,n,Macro(outbound-callerid,${ARG1})
exten => s,n,Set(GROUP()=OUT_${ARG1})
exten => s,n,GotoIf($[ ${GROUP_COUNT()} >
${OUTMAXCHANS_${ARG1}} ]?nochans)
exten => s,n,Set(DIAL_NUMBER=${ARG2})
exten => s,n,Set(DIAL_TRUNK=${ARG1})
exten => s,n,DeadAGI(fixlocalprefix) ; this sets DIAL_NUMBER to the
proper dial string for this trunk
exten => s,n,Set(E164NETWORKS=e164.arpa-e164.info-e164.org) ;
enum networks to check
exten => s,n,GotoIf($["${DIAL_NUMBER:0:1}" = "+"]?begin) ; Skip next
line if it already is prefixed by a plus
exten => s,n,Set(DIAL_NUMBER=+${DIAL_NUMBER}) ; Add a plus to
the start, becasue ENUMLOOKUP needs it.

; start of main network loop


exten => s,n(begin),NoOp(E164NETWORKS is ${E164NETWORKS})
exten => s,n,GotoIf($["${E164NETWORKS:1:2}"=""]?failedtotally)
exten => s,n,Set(ENUMNET=${CUT(E164NETWORKS,-,1)})
exten => s,n,Set(E164NETWORKS=${CUT(E164NETWORKS,-,2-)})

exten => s,n,NoOp(E164NETWORKS is now ${E164NETWORKS})


exten => s,n,NoOp(ENUMNET is ${ENUMNET})

exten =>
s,n,Set(ENUMCOUNT=${ENUMLOOKUP(${DIAL_NUMBER},all,c,${ENU
MNET})})

55
exten => s,n,Set(ENUMPTR=0)
exten => s,n,Set(LOOKUPBUG=0)

; start of main lookup loop


exten =>
s,n(startloop),GotoIf($["${ENUMPTR}"<"${ENUMCOUNT}"]?continue:fail
ed)

; Now, let's start through them.


exten => s,n(continue),Set(ENUMPTR=$[${ENUMPTR}+1])
exten => s,n,NoOp(Doing
ENUMLOOKUP(${DIAL_NUMBER},all,${ENUMPTR},${ENUMNET}))
exten =>
s,n,Set(ENUM=${ENUMLOOKUP(${DIAL_NUMBER},all,${ENUMPTR},${
ENUMNET})})

; Deal with reponse


exten => s,n,GotoIf($["${ENUM:0:3}" = "sip" ]?sipuri)
exten => s,n,GotoIf($["${ENUM:0:3}" = "iax" ]?iaxuri)
; It doesn't matter if you don't have h323 enabled, as when it tries to
dial, it cares
; about dialstatus and retries if there are any enum results left.
exten => s,n,GotoIf($["${ENUM:0:3}" = "h32" ]?h323uri)

; e164.org can return 'ADDRESS' lines. Because of *'s poor handling


of Enum
; lookups, we want to DECREMENT the enum pointer. Yes. That
means we try more
; times than there actually exists entries.
exten => s,n,GotoIf($["${ENUM:0:3}" = "ADD" ]?enumbug)

; OK. If we're here, we've still got some enum entries to go through.
Back to
; the start with you!
exten => s,n,Goto(startloop)

; We're here because of the poor implementation of ENUMLOOKUP in


Asterisk. It
; is quite possible to do three ENUMLOOKUPS and get the same entry
each time.

56
; The only workaround I can think of is when we hit an invalid entry,
do a
; DECREMENT of the pointer, and keep trying.
exten => s,n(enumbug),Set(ENUMPTR=$[${ENUMPTR}-1])
exten => s,n,NoOp(If this is looping with the same ENUM value, The
ENUMLOOKUP function is fixed!)
exten => s,n,Set(LOOKUPBUG=$[${LOOKUPBUG}+1])
; If we've done this more than, ooh, 5 times, then give up on this
network. Sorry.
exten => s,n,GotoIf($["${LOOKUPBUG}" > 5 ]?failed)
exten => s,n,Goto(continue)

; If the prefix is 'sip:'...


exten => s,n(sipuri),Set(DIALSTR=SIP/${ENUM:4})
exten => s,n,Goto(dodial)

; If it's IAX2...
exten => s,n(iaxuri),Set(DIALSTR=IAX2/${ENUM:5})
exten => s,n,Goto(dodial)

; Or even if it's H323.


exten => s,n(h323uri),Set(DIALSTR=H323/${ENUM:5})

exten => s,n(dodial),Dial(${DIALSTR})


exten => s,n,NoOp(Dial exited in macro-enum-dialout with
${DIALSTATUS})

; Now, if we're still here, that means the Dial failed for some reason.
; If it's CONGESTION or CHANUNAVAIL we probably want to try again
on a
; different channel. However, if it's the last one, we don't have any
; left, and I didn't keep any previous dialstatuses, so hopefully
; someone looking throught the logs would have seen the NoOp's
exten =>
s,n,GotoIf($["${ENUMPTR}"<"${ENUMCOUNT}"]?maybemore:dialfailed)
exten => s,n(maybemore),GotoIf($[ $[ "${DIALSTATUS}" =
"CHANUNAVAIL" ] | $[ "${DIALSTATUS}" = "CONGESTION" ]
]?continue)

57
; If we're here, then it's BUSY or NOANSWER or something and well,
deal with it.
exten => s,n(dialfailed),Goto(s-${DIALSTATUS},1)

; Here are the exit points for the macro.


exten => s,n(failed),NoOp(EnumLookup failed on network
${ENUMNET})
exten => s,n,Goto(begin)

exten => s,n(failedtotally),NoOp(EnumLookup failed -- no more


networks to try)
exten => s,n,Goto(end)

exten => s,n(nochans),NoOp(max channels used up)

exten => s,n(end),NoOp(Exiting macro-dialout-enum)

exten => s-BUSY,1,NoOp(Trunk is reporting BUSY)


exten => s-BUSY,2,Busy(20)

exten => _s-.,1,NoOp(Dial failed due to ${DIALSTATUS})

[macro-record-enable]
exten => s,1,GotoIf($[${LEN(${BLINDTRANSFER})} > 0]?2:4)
exten => s,2,ResetCDR(w)
exten => s,3,StopMonitor()
; I haven't figured out how, but occasionally a hung up
; call can end up here. If you don't use DeadAGI (which does
; work fine as a normal AGI), asterisk deadlocks a thread,
; and ends up grumpy.
exten => s,4,DeadAGI(recordingcheck,${TIMESTAMP},${UNIQUEID})
exten => s,5,Noop(No recording needed)
exten => s,999,MixMonitor(${CALLFILENAME}.wav)

;exten => s,3,BackGround(for-quality-purposes)


;exten => s,4,BackGround(this-call-may-be)
;exten => s,5,BackGround(recorded)

; This macro is for dev purposes and just dumps channel/app


variables. Useful when designing new contexts.

58
[macro-dumpvars]
exten => s,1,Noop(ACCOUNTCODE=${ACCOUNTCODE})
exten => s,2,Noop(ANSWEREDTIME=${ANSWEREDTIME})
exten => s,3,Noop(BLINDTRANSFER=${BLINDTRANSFER})
exten => s,4,Noop(CALLERID=${CALLERID(all)})
exten => s,5,Noop(CALLERID(name)=${CALLERID(name)})
exten => s,6,Noop(CALLERID(number)=${CALLERID(number)})
exten => s,7,Noop(CALLINGPRES=${CALLINGPRES})
exten => s,8,Noop(CHANNEL=${CHANNEL})
exten => s,9,Noop(CONTEXT=${CONTEXT})
exten => s,10,Noop(DATETIME=${DATETIME})
exten => s,11,Noop(DIALEDPEERNAME=${DIALEDPEERNAME})
exten => s,12,Noop(DIALEDPEERNUMBER=${DIALEDPEERNUMBER})
exten => s,13,Noop(DIALEDTIME=${DIALEDTIME})
exten => s,14,Noop(DIALSTATUS=${DIALSTATUS})
exten => s,15,Noop(DNID=${DNID})
exten => s,16,Noop(EPOCH=${EPOCH})
exten => s,17,Noop(EXTEN=${EXTEN})
exten => s,18,Noop(HANGUPCAUSE=${HANGUPCAUSE})
exten => s,19,Noop(INVALID_EXTEN=${INVALID_EXTEN})
exten => s,20,Noop(LANGUAGE=${LANGUAGE})
exten => s,21,Noop(MEETMESECS=${MEETMESECS})
exten => s,22,Noop(PRIORITY=${PRIORITY})
exten => s,23,Noop(RDNIS=${RDNIS})
exten => s,24,Noop(SIPDOMAIN=${SIPDOMAIN})
exten => s,25,Noop(SIP_CODEC=${SIP_CODEC})
exten => s,26,Noop(SIPCALLID=${SIPCALLID})
exten => s,27,Noop(SIPUSERAGENT=${SIPUSERAGENT})
exten => s,28,Noop(TIMESTAMP=${TIMESTAMP})
exten => s,29,Noop(TXTCIDNAME=${TXTCIDNAME})
exten => s,30,Noop(UNIQUEID=${UNIQUEID})
exten => s,31,Noop(TOUCH_MONITOR=${TOUCH_MONITOR})
exten => s,32,Noop(MACRO_CONTEXT=${MACRO_CONTEXT})
exten => s,33,Noop(MACRO_EXTEN=${MACRO_EXTEN})
exten => s,34,Noop(MACRO_PRIORITY=${MACRO_PRIORITY})

[macro-user-logon]
; check device type
exten =>
s,1,Set(DEVICETYPE=${DB(DEVICE/${CALLERID(number)}/type)})

59
exten => s,2,GotoIf($["${DEVICETYPE}" = "fixed"]?s-FIXED,1)
; get user's extension
exten => s,3,Set(AMPUSER=${ARG1})
exten => s,4,GotoIf($["${AMPUSER}" = ""]?5:9)
exten => s,5,BackGround(please-enter-your)
exten => s,6,Playback(extension)
exten => s,7,Read(AMPUSER,then-press-pound)
; get user's password and authenticate
exten => s,8,Wait(1)
exten =>
s,9,Set(AMPUSERPASS=${DB(AMPUSER/${AMPUSER}/password)})
exten => s,10,GotoIf($[${LEN(${AMPUSERPASS})} = 0]?s-
NOPASSWORD,1)
; do not continue if the user has already logged onto this device
exten =>
s,11,Set(DEVICEUSER=${DB(DEVICE/${CALLERID(number)}/user)})
exten => s,12,GotoIf($["${DEVICEUSER}" = "${AMPUSER}"]?s-
ALREADYLOGGEDON,1)
exten => s,13,Authenticate(${AMPUSERPASS})
; devices can only be mapped to one user - loggoff anyone else who is
here
exten => s,14,Macro(user-logoff)
; map user to device
exten =>
s,15,Set(AMPUSERDEVICES=${DB(AMPUSER/${AMPUSER}/device)})
exten => s,16,GotoIf($[${LEN(${AMPUSERDEVICES})} = 0]?18)
exten => s,17,Set(AMPUSERDEVICES=${AMPUSERDEVICES}&)
exten =>
s,18,Set(AMPUSERDEVICES=${AMPUSERDEVICES}${CALLERID(num
ber)})
exten =>
s,19,Set(DB(AMPUSER/${AMPUSER}/device)=${AMPUSERDEVICES})
; map device to user
exten =>
s,20,Set(DB(DEVICE/${CALLERID(number)}/user)=${AMPUSER})
; create symlink from dummy device mailbox to user's mailbox
exten => s,21,System(/bin/ln -s
/var/spool/asterisk/voicemail/default/${AMPUSER}/
/var/spool/asterisk/voicemail/device/${CALLERID(number)})

60
exten => s-FIXED,1,NoOp(Device is FIXED and cannot be logged into)
exten => s-FIXED,2,Playback(ha/phone)
exten => s-FIXED,3,SayDigits(${CALLERID(number)})
exten => s-FIXED,4,Playback(is-curntly-unavail)
exten => s-FIXED,5,Playback(vm-goodbye)
exten => s-FIXED,6,Hangup ;TODO should play msg indicated device
cannot be logged into

exten => s-ALREADYLOGGEDON,1,NoOp(This device has already


been logged into by this user)
exten => s-ALREADYLOGGEDON,2,Playback(vm-goodbye)
exten => s-ALREADYLOGGEDON,3,Hangup ;TODO should play msg
indicated device is already logged into

exten => s-NOPASSWORD,1,NoOp(This extension does not exist or no


password is set)
exten => s-NOPASSWORD,2,Playback(an-error-has-occured)
exten => s-NOPASSWORD,3,Playback(vm-goodbye)
exten => s-NOPASSWORD,4,Hangup ;TODO should play msg
indicated device is already logged into

[macro-user-logoff]
; check device type
exten =>
s,1,Set(DEVICETYPE=${DB(DEVICE/${CALLERID(number)}/type)})
exten => s,2,GotoIf($["${DEVICETYPE}" = "fixed"]?s-FIXED,1)
; remove entry from user's DEVICE key
; delete the symlink to user's voicemail box
exten => s,3,System(rm -f
/var/spool/asterisk/voicemail/device/${CALLERID(number)})
exten =>
s,4,Set(DEVAMPUSER=${DB(DEVICE/${CALLERID(number)}/user)})
exten =>
s,5,Set(AMPUSERDEVICES=${DB(AMPUSER/${DEVAMPUSER}/devic
e)})
exten => s,6,DeadAGI(list-item-
remove.php,${AMPUSERDEVICES},${CALLERID(number)},AMPUSERD
EVICES,&)
; reset user -> device mapping

61
; users can log onto multiple devices, need to just remove device from
value
exten =>
s,7,Set(DB(AMPUSER/${DEVAMPUSER}/device)=${AMPUSERDEVICE
S})
; reset device -> user mapping
exten => s,8,Set(DB(DEVICE/${CALLERID(number)}/user)=none)
exten => s,9,Playback(vm-goodbye)

exten => s-FIXED,1,NoOp(Device is FIXED and cannot be logged out


of)
exten => s-FIXED,2,Playback(an-error-has-occured)
exten => s-FIXED,3,Playback(vm-goodbye)
exten => s-FIXED,4,Hangup ;TODO should play msg indicated device
cannot be logged into

[macro-systemrecording]
exten => s,1,Goto(${ARG1},1)

exten => dorecord,1,Record(/tmp/${CALLERID(number)}-


ivrrecording:wav)
exten => dorecord,n,Wait(1)
exten => dorecord,n,Goto(confmenu,1)

exten => docheck,1,Playback(/tmp/${CALLERID(number)}-


ivrrecording)
exten => docheck,n,Wait(1)
exten => docheck,n,Goto(confmenu,1)

exten => confmenu,1,Background(to-listen-to-it&press-1&to-rerecord-


it&press-star|m||macro-systemrecording)
exten => confmenu,n,Read(RECRESULT||1|||4)
exten => confmenu,n,GotoIf($["x${RECRESULT}"="x*"]?dorecord,1)
exten => confmenu,n,GotoIf($["x${RECRESULT}"="x1"]?docheck,1)
exten => confmenu,n,Goto(1)

exten => 1,1,Goto(docheck,1)


exten => *,1,Goto(dorecord,1)

exten => t,1,Playback(goodbye)

62
exten => t,n,Hangup

exten => i,1,Playback(pm-invalid-option)


exten => i,n,Goto(confmenu,1)

exten => h,1,Hangup

;
;
#########################################################
###################
; CallerID Handling
;
#########################################################
###################

;sets the callerid of the device to that of the logged in user


[macro-user-callerid]
exten => s,1,Noop(user-callerid: ${CALLERID(name)}
${CALLERID(number)})
exten => s,n,GotoIf($["${CHANNEL:0:5}" = "Local"]?report)
exten => s,n,GotoIf($["${REALCALLERIDNUM:1:2}" != ""]?start)
exten => s,n,Set(REALCALLERIDNUM=${CALLERID(number)})
exten => s,n(start),NoOp(REALCALLERIDNUM is
${REALCALLERIDNUM})
exten =>
s,n,Set(AMPUSER=${DB(DEVICE/${REALCALLERIDNUM}/user)})
exten =>
s,n,Set(AMPUSERCIDNAME=${DB(AMPUSER/${AMPUSER}/cidname)}
)
exten => s,n,GotoIf($["x${AMPUSERCIDNAME:1:2}" = "x"]?report)
exten => s,n,Set(CALLERID(all)=${AMPUSERCIDNAME}
<${AMPUSER}>)
exten =>
s,n,Set(REALCALLERIDNUM=${DB(DEVICE/${REALCALLERIDNUM}/
user)})
exten => s,n(report),Noop(TTL: ${TTL} ARG1: ${ARG1})
exten => s,n,GotoIf($[ "${ARG1}" = "SKIPTTL" ]?continue)

63
exten => s,n(report2),Set(_TTL=${IF($["foo${TTL}" = "foo"]?64:$[ ${TTL} -
1 ])})
exten => s,n,GotoIf($[ ${TTL} > 0 ]?continue)
exten => s,n,Wait(${RINGTIMER}) ; wait for a while, to give it a chance
to be picked up by voicemail
exten => s,n,Answer()
exten => s,n,Wait(2)
exten => s,n,Playback(im-sorry&an-error-has-occured&with&call-
forwarding)
exten => s,n,Macro(hangupcall)
exten => s,n,Congestion()
exten => s,n(continue),NoOp(Using CallerID ${CALLERID(all)})
exten => h,1,Macro(hangupcall)

; overrides callerid out trunks


; arg1 is trunk
; macro-user-callerid should be called _before_ using this macro
[macro-outbound-callerid]
; Keep the original CallerID number, for failover to the next trunk.
exten => s,1,GotoIf($["${REALCALLERIDNUM:1:2}" != ""]?start)
exten => s,n,Set(REALCALLERIDNUM=${CALLERID(number)})
exten => s,n(start),NoOp(REALCALLERIDNUM is
${REALCALLERIDNUM})

; If this came through a ringgroup or CF, then we want to retain


original CID unless
; OUTKEEPCID_${trunknum} is set.
;
exten => s,n,GotoIf($["${KEEPCID}" != "TRUE"]?normcid) ;Set to TRUE
if coming from ringgroups, CF, etc.
exten => s,n,GotoIf($["x${OUTKEEPCID_${ARG1}}" = "xon"]?normcid)
exten => s,n,GotoIf($["foo${REALCALLERIDNUM}" = "foo"]?normcid) ;if
not set to anything, go through normal processing
exten => s,n,Set(USEROUTCID=${REALCALLERIDNUM})

; We now have to make sure the CID is valid. If we find an AMPUSER


with the same CID, we assume it is an internal
; call (would be quite a conincidence if not) and go through the normal
processing to get that CID. If a device
; is set for this CID, then it must be internal

64
;
exten =>
s,n,GotoIf($["foo${DB(AMPUSER/${REALCALLERIDNUM}/device)}" =
"foo"]?bypass:normcid)

exten =>
s,n(normcid),Set(USEROUTCID=${DB(AMPUSER/${REALCALLERIDN
UM}/outboundcid)})
exten =>
s,n(bypass),Set(EMERGENCYCID=${DB(DEVICE/${REALCALLERIDN
UM}/emergency_cid)})
exten => s,n,Set(TRUNKOUTCID=${OUTCID_${ARG1}})
exten => s,n,GotoIf($["${EMERGENCYROUTE:1:2}" = ""]?trunkcid) ;
check EMERGENCY ROUTE
exten => s,n,GotoIf($["${EMERGENCYCID:1:2}" = ""]?trunkcid) ; empty
EMERGENCY CID, so default back to trunk
exten => s,n,Set(CALLERID(all)=${EMERGENCYCID}) ; emergency cid
for device
exten => s,n,Goto(report)
exten => s,n(trunkcid),GotoIf($["${TRUNKOUTCID:1:2}" = ""]?usercid)
;check for CID override for trunk (global var)
exten => s,n,Set(CALLERID(all)=${TRUNKOUTCID})
exten => s,n(usercid),GotoIf($["${USEROUTCID:1:2}" = ""]?report) ;
check CID override for extension
exten => s,n,Set(CALLERID(all)=${USEROUTCID})
exten =>
s,n,GotoIf($["x${CALLERID(name)}"!="xhidden"]?report:hidecid) ; check
CID blocking for extension
exten => s,n(hidecid),SetCallerPres(prohib_passed_screen) ; Only
works with ISDN (T1/E1/BRI)
exten => s,n(report),NoOp(CallerID set to ${CALLERID(all)})

; Privacy Manager Macro makes sure that any calls that don't pass
the privacy manager are presented
; with congestion since there have been observed cases of the call
continuing if not stopped with a
; congestion, and this provides a slightly more friendly 'sorry' message
in case the user is
; legitamately trying to be cooperative.
;

65
; Note: the following options are configurable in privacy.conf:
;
; maxretries = 3 ; default value, number of retries before failing
; minlength = 10 ; default value, number of digits to be accepted as
valid CID
;
[macro-privacy-mgr]
exten => s,1,Set(KEEPCID=${CALLERID(num)})
exten =>
s,n,GotoIf($["foo${CALLERID(num):0:1}"="foo+"]?CIDTEST2:CIDTEST1)
exten =>
s,n(CIDTEST1),Set(TESTCID=${MATH(1+${CALLERID(num)})})
exten => s,n,Goto(TESTRESULT)
exten =>
s,n(CIDTEST2),Set(TESTCID=${MATH(1+${CALLERID(num):1})})
exten =>
s,n(TESTRESULT),GotoIf($["foo${TESTCID}"="foo"]?CLEARCID:PRIVM
GR)
exten => s,n(CLEARCID),Set(CALLERID(num)=)
exten => s,n(PRIVMGR),PrivacyManager()
exten => s,n,SetCallerPres(allowed_passed_screen); stop gap until
app_privacy.c clears unavailble bit
exten => s,PRIVMGR+101,Noop(STATUS: ${PRIVACYMGRSTATUS}
CID: ${CALLERID(num)} ${CALLERID(name)} CALLPRES:
${CALLLINGPRES})
exten => s,n,Playback(sorry-youre-having-problems)
exten => s,n,Playback(goodbye)
exten => s,n,Playtones(congestion)
exten => s,n,Congestion(5)

;
;
#########################################################
###################
; Inbound Contexts [from]
;
#########################################################
###################

66
[from-sip-external]
;give external sip users congestion and hangup
; Yes. This is _really_ meant to be _. - I know asterisk whinges about
it, but
; I do know what I'm doing. This is correct.
exten => _.,1,NoOp(Received incoming SIP connection from unknown
peer to ${EXTEN})
exten => _.,n,Set(DID=${IF($["${EXTEN:1:2}"=""]?s:${EXTEN})})
exten => _.,n,Goto(s,1)
exten => s,1,Ringing
exten => s,n,GotoIf($["${ALLOW_SIP_ANON}"="yes"]?from-
trunk,${DID},1)
exten => s,n,Set(TIMEOUT(absolute)=15)
exten => s,n,Answer
exten => s,n,Wait(2)
exten => s,n,Playback(ss-noservice)
exten => s,n,Playtones(congestion)
exten => s,n,Congestion(5)
exten => h,1,NoOp(Hangup)
exten => i,1,NoOp(Invalid)
exten => t,1,NoOp(Timeout)

[from-internal]
; applications are now mostly all found in from-internal-additional in
_custom.conf
include => parkedcalls
include => from-internal-custom
;allow phones to dial other extensions
include => ext-fax
;allow phones to access generated contexts
;
; MODIFIED (PL)
;
; Currently the include for findmefollow is being auto-generated before
ext-local which is the desired behavior.
; However, I haven't been able to do anything that I know of to force
this. We need to determine if it should
; be hardcoded into here to make sure it doesn't change with some
configuration. For now I will leave it out
; until we can discuss this.

67
;
include => from-internal-additional
include => ext-local-confirm
; This causes grief with '#' transfers, commenting out for the moment.
; include => bad-number
exten => s,1,Macro(hangupcall)
exten => h,1,Macro(hangupcall)

;------------------------------------------------------------------------
; [bad-number]
;------------------------------------------------------------------------
; This is where all calls go that don't have any other destination
provided
;
;------------------------------------------------------------------------
[bad-number]
exten => _X.,1,Wait(1)
exten => _X.,n,Playback(silence/1&cannot-complete-as-dialed&check-
number-dial-again,noanswer)
exten => _X.,n,Wait(1)
exten => _X.,n,Congestion(20)
exten => _X.,n,Hangup()

exten => _*.,1,Wait(1)


exten => _*.,n,Playback(silence/1&feature-not-avail-
line&silence/1&cannot-complete-as-dialed&check-number-dial-
again,noanswer)
exten => _*.,n,Wait(1)
exten => _*.,n,Congestion(20)
exten => _*.,n,Hangup()
;------------------------------------------------------------------------

[from-zaptel]
exten => _X.,1,Set(DID=${EXTEN})
exten => _X.,n,Goto(s,1)
exten => s,1,NoOp(Entering from-zaptel with DID == ${DID})
; Some trunks _require_ a RINGING be sent before an Answer.
exten => s,n,Ringing()
; If ($did == "") { $did = "s"; }
exten => s,n,Set(DID=${IF($["${DID}"= ""]?s:${DID})})

68
exten => s,n,NoOp(DID is now ${DID})
exten => s,n,GotoIf($["${CHANNEL:0:3}"="Zap"]?zapok:notzap)
exten => s,n(notzap),Goto(from-pstn,${DID},1)
; If there's no ext-did,s,1, that means there's not a no did/no cid
route. Hangup.
exten => s,n,Macro(hangup)
exten => s,n(zapok),NoOp(Is a Zaptel Channel)
exten => s,n,Set(CHAN=${CHANNEL:4})
exten => s,n,Set(CHAN=${CUT(CHAN,-,1)})
exten => s,n,Macro(from-zaptel-${CHAN},${DID},1)
; If nothing there, then treat it as a DID
exten => s,n,NoOp(Returned from Macro from-zaptel-${CHAN})
exten => s,n,Goto(from-pstn,${DID},1)
exten => fax,1,Goto(ext-fax,in_fax,1)

; ##########################################
; ## Ring Groups with Confirmation macros ##
; ##########################################
; Used by followme and ringgroups

;------------------------------------------------------------------------
; [macro-dial-confirm]
;------------------------------------------------------------------------
; This has now been incorporated into dialparties. It still only works
with ringall
; and ringall-prim strategies. Have not investigated why it doesn't
work with
; hunt and memory hunt.
;
;------------------------------------------------------------------------
[macro-dial-confirm]
; This was written to make it easy to use macro-dial-confirm instead
of macro-dial in generated dialplans.
; This takes the same paramaters, with an additional paramater of the
ring group Number
; ARG1 is the timeout
; ARG2 is the DIAL_OPTIONS
; ARG3 is a list of xtns to call - 203-222-240-123123123#-211
; ARG4 is the ring group number

69
; This sets a unique value to indicate that the channel is ringing. This
is used for warning slow
; users that the call has already been picked up.
;
exten => s,1,Set(DB(RG/${ARG4}/${CHANNEL})=RINGING)

; We need to keep that channel variable, because it'll change when we


do this dial, so set it to
; fallthrough to every sibling.
;
exten => s,n,Set(__UNIQCHAN=${CHANNEL})

; The calling ringgroup should have set RingGroupMethod


appropriately. We need to set two
; additional parameters:
;
; USE_CONFIRMATION, RINGGROUP_INDEX
;
; Thse are passed to inform dialparties to place external calls through
the [grps] context
;
exten => s,n,Set(USE_CONFIRMATION=TRUE)
exten => s,n,Set(RINGGROUP_INDEX=${ARG4})
exten => s,n,Set(ARG4=) ; otherwise it gets passed to dialparties.agi
which processes it (prob bug)

exten => s,n,Macro(dial,${ARG1},${ARG2},${ARG3})

; delete the variable, if we are here, we are done trying to dial and it
may have been left around
;
exten => s,n,DBDel(RG/${RINGGROUP_INDEX}/${CHANNEL})
exten => s,n,Set(USE_CONFIRMATION=)
exten => s,n,Set(RINGGROUP_INDEX=)
;------------------------------------------------------------------------

;------------------------------------------------------------------------
; [macro-auto-confirm]
;------------------------------------------------------------------------

70
; This macro is called from ext-local-confirm to auto-confirm a call so
that other extensions
; are aware that the call has been answered.
;
;------------------------------------------------------------------------
[macro-auto-confirm]
exten => s,1,Set(__MACRO_RESULT=)
exten => s,n,DBDel(${BLKVM_OVERRIDE})
exten => s,n,DBDel(RG/${ARG1}/${UNIQCHAN})

;------------------------------------------------------------------------
; [macro-auto-blkvm]
;------------------------------------------------------------------------
; This macro is called for any extension dialed form a queue,
ringgroup
; or followme, so that the answering extension can clear the voicemail
block
; override allow subsequent transfers to properly operate.
;
;------------------------------------------------------------------------
[macro-auto-blkvm]
exten => s,1,Set(__MACRO_RESULT=)
exten => s,n,DBDel(${BLKVM_OVERRIDE})

;------------------------------------------------------------------------
; [ext-local-confirm]
;------------------------------------------------------------------------
; If call confirm is being used in a ringgroup, then calls that do not
require confirmation are sent
; to this extension instead of straight to the device.
;
; The sole purpose of sending them here is to make sure we run
Macro(auto-confirm) if this
; extension answers the line. This takes care of clearing the database
key that is used to inform
; other potential late comers that the extension has been answered by
someone else.
;
;------------------------------------------------------------------------
[ext-local-confirm]

71
exten => _LC-.,1,Noop(IN ext-local-confirm with - RT: ${RT}, RG_IDX:
${RG_IDX})
exten => _LC-.,n,dial(${DB(DEVICE/${EXTEN:3}/dial)},${RT},M(auto-
confirm^${RG_IDX})${DIAL_OPTIONS})

;------------------------------------------------------------------------
; [macro-confirm]
;------------------------------------------------------------------------
; CONTEXT: macro-confirm
; PURPOSE: added default message if none supplied
;
; Follom-Me and Ringgroups provide an option to supply a message to
be
; played as part of the confirmation. These changes have added a
default
; message if none is supplied.
;
;------------------------------------------------------------------------
[macro-confirm]
exten => s,1,Set(LOOPCOUNT=0)
exten => s,n,Noop(CALLCONFIRMCID: ${CALLCONFIRMCID})

; We set ABORT rather than CONTINUE, as we want the server to


forget about this channel
; if it's declined, hung up, or timed out. We don't want it to continue
on to the next
; step in the dialplan, which could be anything!
exten => s,n,Set(__MACRO_RESULT=ABORT)

; ARG1 is the announcement to play to tell the user that they've got a
call they need
; to confirm. Something along the lines of 'You have an incoming call.
Press 1 to accept, 9 to reject'
exten => s,n,Set(MSG1=${IF($["foo${ARG1}" !=
"foo"]?${ARG1}:"incoming-call-1-accept-2-decline")})
exten => s,n(start),Read(INPUT|${MSG1}|1||1|5)

; So. We've now read something, or nothing. We should check to make


sure that the call hasn't

72
; already been answered by someone else. If it has, send this call to
toolate
exten =>
s,n,GotoIf(${DB_EXISTS(RG/${ARG3}/${UNIQCHAN})}?check:toolate)

; We passed that test, so it means the call hasn't been answered. Has
this user pushed 1? If so,
; then go to OK.
exten => s,n(check),GotoIf($["${INPUT}"="1"]?ok)

; If they've pushed 9, then they definately don't want the call. Just
pretend there was no response
; and go to noanswer (or 2 since that will be default for asterisk)
exten => s,n,GotoIf($["${INPUT}"="9"]?noanswer)
exten => s,n,GotoIf($["${INPUT}"="2"]?noanswer)
exten => s,n,GotoIf($["${INPUT}"="3"]?playcid)

; Increment LOOPCOUNT, and check to make sure we haven't played


it 5 times by now. We assume that
; the person is able to push '1' in a reasonably short time.
exten => s,n,Set(LOOPCOUNT=$[ ${LOOPCOUNT} + 1 ])
exten => s,n,GotoIf($[ ${LOOPCOUNT} < 5 ]?start)

; If we're here, that means we've played it MORE than 5 times. Set
__MACRO_RESULT=ABORT, well, just
; coz, and goto fin, which is the last line, meaning it returns to the
previous Dial, and pretends as
; if nothing has happened.
exten => s,n(noanswer),Set(__MACRO_RESULT=ABORT)
exten => s,n,Goto(fin)

; Test play callerid


;
exten => s,n(playcid),Noop(Playing CID: ${CALLCONFIRMCID})
exten => s,n,SayDigits(${CALLCONFIRMCID})
exten => s,n,Goto(start)

; If we're here, it's because the call was already accepted by someone
else.

73
exten => s,n(toolate),Set(MSG2=${IF($["foo${ARG2}" !=
"foo"]?${ARG2}:"incoming-call-no-longer-avail")})
exten => s,n,Playback(${MSG2})
exten => s,n,Goto(noanswer)

; If we made it here, it's because the call _WAS_ accepted, AND it's
still ringing. We delete the
; database entry (so that the DB_EXISTS line above will trigger a
'toolate' jump), and set the
; MACRO_RESULT variable to NOTHING. This is the magic string that
joins both legs of the call together
exten => s,n(ok),DBDel(RG/${ARG3}/${UNIQCHAN})
exten => s,n,DBDel(${BLKVM_OVERRIDE})
exten => s,n,Set(__MACRO_RESULT=)

; The end.
exten => s,n(fin),NoOp(Finished)
exten => h,1,Noop(Hangup Extension in macro-confirm)
exten => h,n,Macro(hangupcall)

;------------------------------------------------------------------------

;
#########################################################
###################
; Extension Contexts [ext]
;
#########################################################
###################

[ext-fax]
exten => s,1,Answer
exten => s,2,Goto(in_fax,1)
exten => in_fax,1,StopPlayTones
exten => in_fax,2,GotoIf($["${FAX_RX}" = "system"]?3:analog_fax,1)
exten => in_fax,3,Macro(faxreceive)
exten => in_fax,4,Hangup
exten => analog_fax,1,GotoIf($["${FAX_RX}" = "disabled"]?4:2) ;if fax is
disabled, just hang up
exten => analog_fax,2,Set(DIAL=${DB(DEVICE/${FAX_RX}/dial)});

74
exten => analog_fax,3,Dial(${DIAL},20,d)
exten => analog_fax,4,Hangup
;exten => out_fax,1,wait(7)
exten => out_fax,1,txfax(${TXFAX_NAME}|caller)
exten => out_fax,2,Hangup
exten => h,1,system(/var/lib/asterisk/bin/fax-process.pl --to
${EMAILADDR} --from ${FAX_RX_FROM} --subject "Fax from
${URIENCODE(${CALLERID(number)})}
${URIENCODE(${CALLERID(name)})}" --attachment
fax_${URIENCODE(${CALLERID(number)})}.pdf --type application/pdf
--file ${FAXFILE});
exten => h,2,Hangup()

;this is where parked calls go if they time-out. Should probably re-


ring
[default]
include => ext-local
exten => s,1,Playback(vm-goodbye)
exten => s,2,Macro(hangupcall)

[incoming]
exten => s,1,Echo ;for testing the connection
;exten => s,1,Playback,demo-thanks ;for playing a file

75
2.11 Lampiran Topologi jaringan VOIP server UNILA

76
77