AF
Asterisk Forum
обсуждения телефонии, VoIP и IP-PBX
12разделов
5 423тем
34 385сообщений
← К списку тем

Управление ограничениями для исходящих вызовов

Newbies/FAQ Forum 17 сообщений -
#1

Добрый день.

Есть астериск 1.8.13
Есть группа междугородних кодов необходимых для разрешения. При этом под шаблоны эти коды не попадают

Писать конструкции вида

exten => _98777XXXXXXX, 1, NoOp(=== Telphin: Outgoing call ===)
exten => _98777XXXXXXX, n, Dial(sip/${EXTEN:1}@telphin,,HTt)
exten => _98666XXXXXXX, 1, NoOp(=== Telphin: Outgoing call ===)
exten => _98666XXXXXXX, n, Dial(sip/${EXTEN:1}@telphin,,HTt)
и тд

несколько странно и долго. с ужасом представлю себе километровые конфиги в последствии.

Возможно ли использование сделать группу из этих кодов, хранимую где либо

[allow_city]
8888
6666
7777

И использовать ее для разрешения звонков в контексте?

[long_distans]
exten => _9${allow_city}XXXXXXX, 1, NoOp(=== Telphin: Outgoing call ===)
exten => _9${allow_city}XXXXXXX, n, Dial(sip/${EXTEN:1}@telphin,,HTt)

Может быть есть какие то другие решения по хранению "разрешенных" кодов и подставлению из в нужные контексты?
#3

Цитата:
Есть группа междугородних кодов необходимых для разрешения. При этом под шаблоны эти коды не попадают
Писать конструкции вида


У вас вопрос несколько непонятен:

1. Вам надо разрешить звонить на определенные направления определенным группам/абонентам вашей организации?
или
2. У вас много направлений, много операторов и хотите сделать перебор направлений через этих операторов?

Почему "под шаблоны эти коды не попадают "?

Если у вас первый вопрос, с разрешениями, вариантов реализации множество. Без изпользования баз данных и громоздких дайлпланов. Например:

макро нормализации набраного номера (городской, через 8-у, 8-10, 00 если надо)
И дайлплан с разрешенными направлениями

ИЛИ

в sip.conf на каждом пользователе:
[user_anthony]
Set=call_permissions=0001 ; International, special numbers, intercity, local numbers bits

макро нормализации набраного номера,
макро проверки прав набора,
сам дайлплан
#4

andyk74 @ Сб Окт 27, 2012 00:56 писал(а):
Цитата:
Есть группа междугородних кодов необходимых для разрешения. При этом под шаблоны эти коды не попадают
Писать конструкции вида


У вас вопрос несколько непонятен:

1. Вам надо разрешить звонить на определенные направления определенным группам/абонентам вашей организации?
или

Почему "под шаблоны эти коды не попадают "?

Если у вас первый вопрос, с разрешениями, вариантов реализации множество. Без изпользования баз данных и громоздких дайлпланов. Например:

макро нормализации набраного номера (городской, через 8-у, 8-10, 00 если надо)
И дайлплан с разрешенными направлениями

ИЛИ

в sip.conf на каждом пользователе:
[user_anthony]
Set=call_permissions=0001 ; International, special numbers, intercity, local numbers bits

макро нормализации набраного номера,
макро проверки прав набора,
сам дайлплан

спасибо за рекомендации.
базы данных для меня пока отдельная, не изведанная сущность, использовать их - еще одна точка отказа, без умения траблшутить-управлять.
нужно именно разрешить определенным группам звонить на определенные направления без создания громоздких диалпланов.

Коды конечно попадают под шаблоны, но даже в случае шаблонов это далеко не пара строк.
про макронормализаци почитаю, пока для меня это что то неизведанное )


пока думаю вот про такое.

будет файл(ы) с разрешенными кодами.
в диалплане конструкция с системным вызовом grep

exten => _989XXXXXXXXX,1,Gotoif( здесь страшная конструкция с вызовом grep -q ${EXTEN:0:3} имяфайласкодами и если true - разрешить звонить иначе завернуть на заглушку)
#5

родил.
вызываю скрипт проверку на существование кода мобильника в файле, если есть - присваиваем 1 и в GotoIf звоним, если нет - выходим

Код:

[gsm_len_obl]
include => local_call
exten => _989XXXXXXXXX, 1, NoOp(=== Telphin: GSM Outgoing call ===)
exten => _989XXXXXXXXX, 2, Set(result=${SHELL(/etc/asterisk/allow_dial_code/check.sh ${EXTEN:2:3} && echo -n 1 || $
exten => _989XXXXXXXXX, 3, GotoIf( $["${result}" = "1"]?4:5)
exten => _989XXXXXXXXX, 4, Dial(sip/${EXTEN:1}@telphin,,HTt)
exten => _989XXXXXXXXX, 5, Hangup()


Код:

cat /etc/asterisk/allow_dial_code/check.sh
[sudo] password for mda:
#! bin/bash
grep -q $1 /etc/asterisk/allow_dial_code/len.obl.gsm
a=$?
#echo $a
if [ "$a" != "0" ]
then exit 1
fi


Код:

cat /etc/asterisk/allow_dial_code/len.obl.gsm
901
903
904
905
906
909
911
921
929
931
950
951
952
953
960
961
962
963
964
965
981


но осознал, что это неверный путь для разрешения городов.
проверка у меня основывается на том, что код - трехзначный. и для GSM вполне годится
а ведь есть и четырех и пяти-значные коды для городов.

можно как то коды отсекать? типа вводите решетку или после введения кода дождаться гудка?
#6

Посмотрите тут: http://wapo-spb.livejournal.com/5980.html
_________________
P4 3.0 + 1Gb CentOS 5.8 Aster 1.8.16
Не люблю gui-сборки: натуральный продукт вкуснее.
И еще: я ПРОФИ так как НЕ ЛЕНЮСЬ читать литературу.
#7

У вас база, а он хочет консоль. И в принципе, на этом уровне (ограничение звонков на направления), хватит и просто консоли, возможно с генератором дайлплана.

С базой однако будет попроще, менше возни..

Added after 4 minutes:

через пару часов скину решение, которое у нас было года 4 назад. система обслуживала 200 активных звонков (небольшой оператор телеофнии для компаний), база была сильно загружена, потому мы все, что могли, делали в консоли. Решение досталось в наследство, иногда база давала лаги в секунды, что неприемлимо.
#8

Wapo @ Пн Окт 29, 2012 11:18 писал(а):
Посмотрите тут: http://wapo-spb.livejournal.com/5980.html

отличное решение, спасибо.
как буду уверен в силах управлять mysql - обязательно осилю.

Added after 1 minutes:

andyk74 @ Пн Окт 29, 2012 14:42 писал(а):
У вас база, а он хочет консоль. И в принципе, на этом уровне (ограничение звонков на направления), хватит и просто консоли, возможно с генератором дайлплана.

С базой однако будет попроще, менше возни..

Added after 4 minutes:

через пару часов скину решение, которое у нас было года 4 назад. система обслуживала 200 активных звонков (небольшой оператор телеофнии для компаний), база была сильно загружена, потому мы все, что могли, делали в консоли. Решение досталось в наследство, иногда база давала лаги в секунды, что неприемлимо.


вы правы - нужна консоль изза (временного, как я надеюсь))) неумения работать с базами.
заранее спасибо )
#9

Заранее говорю, дайлплан нe для России, надо будет слегка поправить, я небольшой пример сделал ниже.
Примера не нашел, написал сейчас. Должно работать или работать с минимальными изменениями.

Код:
; sip.conf
[test_user]

Set=ENABLED_DESTINATIONS=1101 ; ; Заграница, спец. номера, межгород, сотовые

;extensions.conf:
[outgoing]
; Все звонки от сип телефонов пользователей приходят сюда
; Вначале нормализуем номер, приведем в формат е164,
; После перевода в е164, звонок уйдет на "правильный" контекст
; для дальнейшей обработки

; Скорая, милиция и далее, сразу звоним
exten => _0[123],1,Goto(dial_out,${EXTEN},1)
exten => 112,1,Goto(dial_out,${EXTEN},1)

; Короткие номера в пределах данной станции (2ХХХ)
; Сразу звоним
exten => _2XXX,1,Goto(dial_out,${EXTEN},1)

; Сервисные номера (у меня 1ХХХ или 19ХХХ)
exten => _1XXX,1,Goto(outgoing_special,${EXTEN},1)
exten => _19XXX,1,Goto(outgoing_special,${EXTEN},1)

; Россия, набор через 8-у
exten => _8XXXXXXXXXX,1,Goto(outgoing_russia,7${EXTEN:1},1)

; Россия через 00
exten => _007XXXXXXXXXX,1,Goto(outgoing_russia,${EXTEN:2},1)

; Испания, обычно номера начинаются через 6 или 9 и длина номера 9 знаков
; остальных кодов мне не было нужно
exten => _[69]XXXXXXXX,1,Goto(0034${EXTEN},1)

; Все остальное, что надо включить
; exten => _ЧТОТО,1,Goto(check_SOMETHING,SOME_PREFIX${EXTEN:CUT_N_DIGITS},1)

; заграница через плюс
exten => _+Z!,1,Goto(00${EXTEN:1},1)

; заграница через 011, для США, Канады и некоторых других стран.
exten => _011XXXXXXX.,1,Goto(00${EXTEN:3},1)

; заграница через 810, для России и некоторых других стран.
exten => _810XXXXXXX.,1,Goto(00${EXTEN:3},1)

; заграница через 00
exten => _00XXXXXXX.,1,Goto(check_international,${EXTEN:2},1)

; Все, что не описано в контексте, соответственно не будет работать

[outgoing_special]
; В эти контексты попадают нормализованные номера, короткие, которые разрешены
; или номера публичной телефонной сети в формате е164
; Сейчас проверим, можно ли звонить на конкретные направления с этого конкретного сип телефона
; Берем бит из переменной, "привязанной" к сип-телефону (см. sip.conf)

: Set=ENABLED_DESTINATIONS=1101 ; Заграница, спец. номера, межгород, сотовые
; второй бит
exten => _X!,1,GotoIf($["${ENABLED_DESTINATIONS:2:1}"="1"]?dial_out,${EXTEN},1:disallowed_destination,${EXTEN},1)

[outgoing_russia]
; Спец номера с повышенным тарифом (трактуем их как международные)
; просто переходим на другой контекст
exten => 7900XXXXXXX,1,Goto(outgoing_international,${EXTEN},1)

; Сотовые
: Set=ENABLED_DESTINATIONS=1101 ; Заграница, спец. номера, межгород, сотовые
; последний 4-й бит
exten => 79XXXXXXXXX,1,GotoIf($["${ENABLED_DESTINATIONS:4:1}"="1"]?dial_out,${EXTEN},1:disallowed_destination,${EXTEN},1)

; Города и бесплатные номера 8-800 и т.д.
; Что можно доделать, это проверку своего города и правил звонков.
: Set=ENABLED_DESTINATIONS=1101 ; Заграница, спец. номера, межгород, сотовые
; третий бит
exten => 7[0-8]XXXXXXXXX,1,GotoIf($["${ENABLED_DESTINATIONS:3:1}"="1"]?dial_out,${EXTEN},1:disallowed_destination,${EXTEN},1)

[outgoing_international]
: Set=ENABLED_DESTINATIONS=1101 ; Заграница, спец. номера, межгород, сотовые
; первый бит
exten => _X!,1,GotoIf($["${ENABLED_DESTINATIONS:1:1}"="1"]?dial_out,${EXTEN},1:disallowed_destination,${EXTEN},1)

[disallowed_destination]
exten => _X!,1,Answer
exten => _X!,n,Playback(call-to-this-destination-is-not-allowed-please-contact-administrator)
exten => _X!,n,Busy(8)
exten => _X!,n,Hangup

[dial_out]
; В этом контексте мы определяем правила набора разных направлений и через разные транки.
; Пара примеров

; Скорая, милиция и далее, сразу звоним
exten => _0[123],1,Dial(SIP/pstn_gateway/${EXTEN},60)
exten => _0[123],n,Busy(8)
exten => _0[123],n,Hangup

exten => 112,1,Dial(SIP/pstn_gateway/${EXTEN},60)
exten => 112,n,Busy(8)
exten => 112,n,Hangup

; Короткие номера в пределах данной станции (2ХХХ)
; Сразу звоним
exten => _2XXX,1,Dial(SIP/${EXTEN},60)
exten => _2XXX,n,Busy(8)
exten => _2XXX,n,Hangup


; Сервисные номера (у меня 1ХХХ или 19ХХХ)
exten => _1XXX,1,Dial(SIP/pstn_gateway/${EXTEN},60)
exten => _X!,n,Busy(8)
exten => _X!,n,Hangup

exten => _19XXX,1,Dial(SIP/pstn_gateway/${EXTEN},60)
exten => _X!,n,Busy(8)
exten => _X!,n,Hangup

; Россия 900-е номера
exten => _7900XXXXXXXX,1,Answer
exten => _7900XXXXXXXX,n,Playback(sleep/4&beep&beep&beep&sleep/1&call-to-this-number-is-very-expensive-hangup-if-unsure&sleep/4)
exten => _7900XXXXXXXX,n,Dial(SIP/pstn_gateway/${EXTEN},60)
exten => _7900XXXXXXXX,n,
exten => _7900XXXXXXXX,n,

; Россия сотовые
exten => _79XXXXXXXXXX,1,Dial(SIP/megafon/8${EXTEN:1},60)
exten => _79XXXXXXXXXX,n,Dial(SIP/beeline/8${EXTEN:1},60)
exten => _79XXXXXXXXXX,1,Dial(SIP/pstn_gateway/8${EXTEN:1},60)
exten => _79XXXXXXXXXX,n,
exten => _79XXXXXXXXXX,n,

; Россия, остальное
exten => _7[0-8]XXXXXXXXXX,1,Dial(SIP/lowratevoip/+${EXTEN},60)
exten => _7[0-8]XXXXXXXXXX,n,Dial(SIP/easyvoip/+${EXTEN},60)
exten => _7[0-8]XXXXXXXXXX,n,Dial(SIP/telphin/810${EXTEN},60)
exten => _7[0-8]XXXXXXXXXX,n,Dial(SIP/something_else/${EXTEN},60)
exten => _7[0-8]XXXXXXXXXX,n,Busy(8)
exten => _7[0-8]XXXXXXXXXX,n,Hangup

; Испания
...
; Великобритания
...

; Остальное, самый короткий код страны с номером телефона - 8 знаков (наприме, Гибралтар: 3+5)
exten => _ZXXXXX!,1,Dial(OPERATOR1)
exten => _ZXXXXX!,n,Dial(OPERATOR2)
exten => _ZXXXXX!,n,Dial(OPERATOR3)
exten => _ZXXXXX!,n,Dial(OPERATOR4)
exten => _ZXXXXX!,n,Answer
exten => _ZXXXXX!,n,Playback(sleep/4&beep&beep&beep&sleep/1&call-to-this-number-is-very-expensive-hangup-if-unsure&sleep/4)
exten => _ZXXXXX!,n,Dial(SIP/pstn_gateway/810${EXTEN},60)
exten => _ZXXXXX!,n,Busy(8)
exten => _ZXXXXX!,n,Hangup
#10

полезный конфиг, спасибо!

вообще - я балбес.
под шаблоны попадает (в случае gsm и гарантированных 3 знаков в коде) все что угодно
например для кодов ленобласти.

Код:

exten => _989[0-3568][0-69]XXXXXXX, 1, NoOp(=== Telphin: GSM Outgoing call ===)
exten => _989[0-3568][0-69]XXXXXXX, 2, Answer
exten => _989[0-3568][0-69]XXXXXXX, n, Dial(sip/${EXTEN:1}@telphin,,HTt)


вместо моего нагромождения из проверки скриптом.

обратно можно сделать шаблоны для [3-5] значных кодов межгорода.
#11

гм, не уверен что работает (и я правильно составил алгоритм), нет под рукой машины для проверки.
Извините, если что не так.


Код:

exten => _810.,1,NoOp()
same => n,Macro(check-and-call,telphin,810,${CALLERID(name)},${CALLERID(num)},${EXTEN:3},120,Ttrog)
same => n, Hangup()

exten =>_[7-8].,1,NoOp()
same => n,Macro(check-and-call,telphin,8,${CALLERID(name)},${CALLERID(num)},${EXTEN:1},120,Ttrog)
same => n, Hangup()

[Macro-check-and-call]
exten => s,1,NoOp( in !--> check-and-call)
same => n,Set(dial_or_not=0)
same => n,AGI(/etc/asterisk/script/check_num_on_dial.sh,${ARG5})
same => n,GoToIf($[${dial_or_not}="1"]?go_to_dial:sorry_go_out)
same => n(go_to_dial),Dial(SIP/${ARG2}${ARG5}@${ARG1},${ARG6},${ARG7})
same => n,NoOp( out n,MacroExit()
same => n(sorry_go_out),NoOp( out n,MacroExit()




Код:

#!/bin/bash
num_is=$1
len_num=${#num_is}
i=1

while [ $i -le $len_num ]
do
tmp_num=${num_is:0:$i}
grep -qx $tmp_num /etc/asterisk/list/good_num.list
dial_or_not=$?
if [ "$dial_or_not" == "0" ]
then
echo "SET VARIABLE dial_or_not 1"
break
fi
i=$(( $i + 1 ))
done


Одно но! Если у Вас есть в good_num.list к примеру 495 и 4951112233 то он вывалится на 495 с dial_or_not=1.

_________________
Мы всегда можем уметь...


Последний раз редактировалось: nikto (Ср Окт 31, 2012 13:24)
#12

Я решил у себя с помощью MySQL+PHP+AGI и GotoIf.
_________________
Внимание! Свет в конце тоннеля может быть светом фар приближающегося поезда!
Ubuntu 10.04/12.04 - Asterisk 1.8.11.0-rc2/1.8.14.1/1.8.17.0/10.10.0
#13

nikto @ Вт Окт 30, 2012 13:41 писал(а):
гм, не уверен что работает (и я правильно составил алгоритм), нет под рукой машины для проверки.
Извините, если что не так.


Код:

exten => _810.,1,NoOp()
same => n,Macro(check-and-call,telphin,810,${CALLERID(name)},${CALLERID(num)},${EXTEN:3},120,Ttrog)
same => n, Hangup()

exten =>_[7-8].,1,NoOp()
same => n,Macro(check-and-call,telphin,8,${CALLERID(name)},${CALLERID(num)},${EXTEN:1},120,Ttrog)
same => n, Hangup()

[Macro-check-and-call]
exten => s,1,NoOp( in !--> check-and-call)
same => n,Set(dial_or_not=0)
same => n,AGI(/etc/asterisk/script/check_num_on_dial.sh,${ARG5})
same => n,GoToIf($[${dial_or_not}="1"]?go_to_dial:sorry_go_out)
same => n(go_to_dial),Dial(SIP/${ARG2}${ARG5}@${ARG1},${ARG6},${ARG7})
same => n,NoOp( out n,MacroExit()
same => n(sorry_go_out),NoOp( out n,MacroExit()




Код:

#!/bin/bash
num_is=$1
len_num=${#num_is}
i=1

while [ $i -le $len_num ]
do
tmp_num=${num_is:0:$i}
grep -qx $tmp_num /etc/asterisk/list/good_num.list
dial_or_not=$?
if [ "$dial_or_not" == "0" ]
then
echo "SET VARIABLE dial_or_not 1"
break
fi
i=$(( $i + 1 ))
done


Одно но! Если у Вас есть в good_num.list к примеру 495 и 4951112233 то он вывалится на 495 с dial_or_not=1.


очень познавательно! спасибо за помощь!
#14

в прошлый раз не было возможности подробно рассказать о способе, каким я решил проблему выбора канала по коду. Так как каналов у меня всего два (для местной и междугородней связи), то и диал-план достаточно простой. Но задел на будущее я оставилSmile
Итак, как я выше писал, использую MySQL+AGI+PHP.
Создал таблицу call_control в базе asterisk из двух полей:
Код:

--------------------
! code ! direct !
--------------------
! 926% ! 1 !
--------------------
! 925% ! 1 |
--------------------

И так далее по кодам.
Далее, план набора:
Код:

exten => _89.,1,AGI(call_control.php,${EXTEN:1})


В файле всё просто, запрос в базу:
Код:

$query="SELECT direct FROM `asterisk`.`call_control` WHERE '$argv[1]' like `code`";

Так как коды уникальные, то обработка результата минимальна.
Код:

$result=mysql_query($query);
$num_rows=mysql_num_rows($result);

if ($num_rows==1)
{
$agi->set_variable('DIRECT', "1");
}
else
{
$agi->set_variable('DIRECT', "2");
}

Далее, план набора:
Код:

exten => _89.,2,GotoIf($[${DIRECT}=1?3:4]) - если первое направление, то звоним через первый канал, если не первое, то через второй
exten => _89.,3,Goto(out_gorod,${EXTEN},1)
exten => _89.,4,Goto(out_national,${EXTEN},1)

Если направлений больше 1, то путём несложных исправлений получаем довольно-таки простой выбор канала. При этом шаблоны для каналов могут быть одинаковыми. В моём примере:
Код:

[out_gorod]
exten => _89.,1,Dial(SIP/out_1/${EXTEN})
...

[out_national]
exten => _89.,1,Dial(SIP/out_2/${EXTEN})
...

Номер канала можно также брать и из переменной. К примеру, если есть 5 разных направлений, то вместо GotoIf достаточно написать так:
Код:

exten => _89.,2,Goto(out_${DIRECT},${EXTEN},1)

Или проще, чтобы не городить каждому направлению свой контекст:
Код:

exten => _89.,2,Dial(SIP/out_${DIRECT}/${EXTEN})


Однако, если в таблице будут такие строки:
Код:

-----------------------
! code ! direct !
-----------------------
! 926% ! 1 !
-----------------------
! 926222% ! 2 !
-----------------------

то надо будет усложнить обработку результата циклом, в котором будет определяться самая большая длина поля code. Таким образом будет всегда определяться единственное направление связи.
Надеюсь, что данное решение не столь сложное и грубоеSmile
Критика приветствуется.

P.S. PHP выбран потому, что я с ним лучше дружуSmile

_________________
Внимание! Свет в конце тоннеля может быть светом фар приближающегося поезда!
Ubuntu 10.04/12.04 - Asterisk 1.8.11.0-rc2/1.8.14.1/1.8.17.0/10.10.0
#15

Ваше решение ок, но будет плохо работать при нагрузке:

У вас не фастаги, а обычное: астериск при каждом обращении:
1. вызывает аги
2. значит грузит что то с диска, ладно это кэшируемо...
3. аги открывает базу (заниемает ресурсы)
4. читает данные
5. закрывает базу.

Вам нужно делать решение на фастаги, то что есть уже при 70 одновременных звонках будет нестабильно.

А еще лучше задействовать func_odbc и напрямую обращаться к базе:
Код:
; func_odbc.conf
[BLACKLISTED]
dsn=asterisk
readsql=SELECT number_e164 FROM blacklists WHERE number_e164='${SQL_ESC(${ARG1})}' AND blocked='1'

; extensions.conf

exten => _Z!,1000(check_permissions),NoOp()
exten => _Z!,n,Set(ARRAY(call_allowed,e164_prefix,playback_files)=${ODBC_BLACKLISTED(${caller_id})})
exten => _Z!,n,Goto(allowed_${call_allowed})
exten => _Z!,n(allowed_),NoOp()
exten => _Z!,n(allowed_0),Goto(blocked_destination,${EXTEN},play_audio)
exten => _Z!,n(allowed_1),Goto(open_destination,${EXTEN},send_call)


Часть 2:
Это лично мой заскок, я считаю, что если можно не особо напрягаясь сделать решение без усложнения системы, следует так делать. Большинство моих (весьма сложных) систем спосовно работать на openwrt роутере только на астериске.

Дайпплан и возможности обработки самого астеирска очень гибкие.
#16

Я и не спорю, что моё решение не идеально, более того - до совершенства ему ого-го сколько. Я решал для себя одну задачу, не рассчитанную на большую нагрузку. И решил поделиться.
А за Ваш пример - огромное спасибо, буду изучать и учиться!Smile

_________________
Внимание! Свет в конце тоннеля может быть светом фар приближающегося поезда!
Ubuntu 10.04/12.04 - Asterisk 1.8.11.0-rc2/1.8.14.1/1.8.17.0/10.10.0
#17

очень спасибо всем написавшим всякое в топик.
andyk74 - отдельное спасибо за расстановку точек с вызовами AGI скриптов. понимание экономии ресурсов (в разрезе вызовов) не только для астериска работает, но и для многих других решений.