понедельник, мая 14, 2012

Генерация ложных гудков в трубку после перевода звонка в отвеченное состояние


Настраивал недавно одному клиенту Asterisk. До этого у них стоял тоже астериск, который был настроен каким то "умельцем" - настолько запутанного диалплана я, наверное, не видел ни разу за свою шестилетнюю практику работы. Но пост не об этом. В общем, переводили мы клиента с "их" астериска на "наш" астериск. Вроде бы всё перенесли и система удачно запустилась, но возник один нюанс - у клиента есть 2 GSM-модема, подключенных к FXO-портам шлюзов Linksys SPA3102. И через эти модемы осуществляются звонки на Московские мобильные. На старой системе, при звонке через модемы, в трубку абоненту генерился ложный гудок до тех пор, пока не начинал генерироваться настоящий гудок вызываемой стороной. Ничего сложного, подумал я - поставим опцию r и дело с концом. Но всё оказалось несколько сложнее.Оказывается, при звонке на порт FXO линксис, GSM-модем, подключенный к этому порту сразу же переводил канал в отвеченное состояние и давал в трубку тишину в течение ~20 секунд до тех пор, пока не начинала "гудеть" вызываемая сторона. Скажу честно, с такой проблемой я столкнулся впервые, а клиент говорил, что на старой системе всё работало.
После нескольких дней курения диалпланов предыдущей системы и мануалов в интернете я был в тупике, но, к счастью, интуиция и опыт подсказали ответ - опция G в команде Dial. В описании этой опции говорится:
G(context^exten^pri): If the call is answered, transfer both parties to the specified context and extension. The calling party is transferred to priority x, and the called party to priority x+1. This allows the dialplan to distinguish between the calling and called legs of the call (new in v1.2). You cannot use any options that would affect the post-answer state if this option is used.
что в примерном переводе на русский язык означает следующее:
Если вызов отвечен, он переводится на специальный контекст и указанный экстеншен. Притом, звонящий канал будет переведён на приоритет x, а вызываемый канал на приоритет x+1
В итоге, был составлен "специфичный" контекст следующего содержания:
[custom-test-out-ring]
exten => s,1,Goto(chan_a)
exten => s,n,Goto(chan_b)
exten => s,n(chan_a),Ringing()
exten => s,n,Wait(20)
exten => s,n,Bridge(${DIALEDPEERNAME})
exten => s,n,Hangup()
exten => s,n(chan_b),Wait(50)
exten => s,n,Hangup()
Вызов данного контексте осуществляется следующим образом:

exten => _8XXXXXXXXXX,n,Dial(SIP/linksys/${EXTEN},3,tTG(custom-test-out-ring^s^1))

В итоге, когда осуществляется вызов на указанное направление, при ответе на вызов звонок перекидывается в контекст custom-test-out-ring, в котором звонящий канал переводится на именованный приоритет chan_a, а вызываемый канала - на chan_b. Опытным путём была измерена задержка, которую даёт модем перед тем, как начинает посылать сигналы вызова в трубку и, соответствующее значение было установлено в команду Wait для канала А. Вот таким бесхитростным, вобщем то способом, была решена довольно нетривиальная задача.