Transcript

1

PENDAHULUAN

2

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.

3

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.

4

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.

5

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

6

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).

7

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.

8

INSTALASI VOIP SERVER UNILA

9

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

10

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

11

• Klik System Administration Untuk masuk ke menu System administration

• Isi user dengan maint

• Isi Password dengan wuelektro

• Klik OK untuk melanjutkan

12

2.4 Menu System Administration

• Klik Menu FreePBX untuk masuk ke Menu FreePBX

13

• Klik Menu Tools

• Pertama kali kita harus melakukan instalasi module: Core

14

2.5 Menu Tools

• Klik Module Admin

15

• Beri Tanda centang pada Core (core)

• Pilih Enable Selected dan kemudian Submit

• Klik Menu Setup

16

2.6 Menu Setup

• Klik Menu Extensions

• Pada Menu Add an Extensions

Klik Menu SIP

17

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

18

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

Untuk menyimpan hasil perubahan.

19

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

20

• 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

21

• 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

22

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

23

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

24

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

25

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

26

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

27

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.

28

29

30

31

32

33

34

35

36

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

37

- 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

38

; 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

39

[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

40

; 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)

41

; 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

42

;

#########################################################

###################

; 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)

43

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}:"")})

44

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)

45

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

46

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

47

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

[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)

48

; 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})

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

49

; 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

50

; 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)

51

; 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})

52

; 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

53

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]

54

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()

55

; 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})})

56

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.

57

; 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)

58

; 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.

59

[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)})

60

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)})

61

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

62

; 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)

63

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)

64

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

65

;

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.

;

66

; 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]

;

#########################################################

###################

67

[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.

68

;

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})})

69

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

70

; 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]

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

71

; 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]

72

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

73

; 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.

74

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)});

75

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

76

2.11 Lampiran Topologi jaringan VOIP server UNILA

77

top related