Limitação do número de ligações simultâneas via IAX
Autor: Marcelo Terres | Publicado: 2014-01-22T11:00:00-02:00





Uma situação bastante comum quando você precisa interligar duas (ou mais) filiais via IAX para que os usuários de ambos locais possam falar sem custo entre si, é a existência de uma banda limitada para o uso de voz.



Quando temos este cenário, normalmente surge um problema: como podemos garantir que não teremos mais ligações simultâneas do que permite a "banda reservada" para este recurso.



Com esta demanda nas mãos, criei um plano de discagem que permite limitar o número de ligações simultâneas quando for utilizado IAX2 (ou, com pequenas adaptações, qualquer outro tipo de canal, como, por exemplo, SIP).



Para efeito de demonstração, vamos supor que você utilize um codec que consuma 64Kbps para cada ligação (G.711 a-law). Vamos supor também que você tenha 256Kbps disponível para voz, podendo realizar então até quatro ligações simultâneas sem perda na qualidade (cortes, "voz robótica", etc...).



A configuração necessária para tal controle é feita no extensions.conf, em três contextos diferentes (não esqueça de adaptar o exemplo à sua realidade):


o contexto [globals] é padrão do Asterisk e nele você pode declarar variáveis para uso no plano de discagem;
o contexto [from-iax] é o contexto que controlará as chamadas recebidas via IAX;
o contexto [saidaexterna] é o contexto de saída das chamadas (exceto chamadas entre ramais locais);


Contexto globals


No contexto [globals] você irá declarar a variável que controla o número máximo de chamadas permitidas, da seguinte forma:


; Controle de chamadas
; 256Kbps &nbsp;= 4 chamadas a-law de 64Kbps cadaCALL_LIMIT_IAX=4&nbsp;



Contexto from-iax


No contexto [from-iax] &nbsp;você irá controlar as chamadas entrantes via IAX, da seguinte forma:


exten =&gt; _XXXX.,1,NoOp(Chamada via IAX)
same =&gt; n,NoOP(Chamada de origem ${CALLERID(num)} discando para ${EXTEN}); Adiciona chamada no grupo do IAX2same =&gt; n,NoOP(Adicionando chamada entrante ao grupo IAX2)same =&gt; n,Set(GROUP()="IAX2"); verifica o número de chamadas simultâneas no gruposame =&gt; n,Set(SIMULTCALL=${GROUP_COUNT("IAX2")})same =&gt; n,NoOp(Ligacoes em curso IAX2: ${SIMULTCALL} de ${CALL_LIMIT_IAX}); verifica se a chamada pode ser realizadasame =&gt; n,GotoIf($[0${SIMULTCALL} &lt;= 0${CALL_LIMIT_IAX}]?call:nocall); seção utilizada quando a chamada não pode ser realizadasame =&gt; n(nocall),NoOp(Limite de chamadas IAX2 excedido - chamada entrante recusada)same =&gt; n,Playback(canais_iax_ocupados)same =&gt; n,Hangup(); seção utilizada para realização da chamada para ramais (sip)same =&gt; n(call),Goto(sip,${EXTEN},1)same =&gt; n,Hangup()

Contexto saidaexterna


No contexto [saidaexterna] você irá controlar as chamadas saintes via IAX e outras tecnologias como DAHDI, Khomp ou DGV, da seguinte forma:


exten =&gt; _X.,1,Progress
; AGI para obter a variável de discagem ${DIAL} com base no destino da ligação;; As saídas possíveis são, por exemplo:; Khomp/Gebt/${EXTEN}; Khomp/Ggsm/${EXTEN}; DGV/g1/${EXTEN}; IAX2/SPO/${EXTEN}; SIP/vono/${EXTEN};; Não vou postar o AGI porque ele é muito específico para a solução; mas você pode gerar o seu próprio AGI com base na sua estrutura;same =&gt; n,AGI(dialout.agi); Obtém o tipo de canal de saídasame =&gt; n,Set(OUTCHAN=${DIAL:0:4}); Verifica se o canal é IAX2. Se não for IAX2 vai diretamente para a discagemsame =&gt; n,GotoIf($["${OUTCHAN}"="IAX2"]?iax:call); Adiciona chamada no grupo IAX2same =&gt; n(iax),NoOP(Adicionando chamada sainte ao grupo IAX2)same =&gt; n,Set(GROUP()="IAX2"); verifica o número de chamadas simultâneas IAX2same =&gt; n,Set(SIMULTCALL=${GROUP_COUNT("IAX2")})same =&gt; n,NoOp(Ligacoes em curso IAX2: ${SIMULTCALL} de ${CALL_LIMIT_IAX}); verifica se a chamada pode ser realizadasame =&gt; n,GotoIf($[0${SIMULTCALL} &lt;= 0${CALL_LIMIT_IAX}]?call:nocall); seção usada quando a chamada não pode ser realizadasame =&gt; n(nocall),NoOp(Limite de chamadas IAX2 excedido - chamada sainte recusada)same =&gt; n,Playback(canais_iax_ocupados)same =&gt; n,Hangup(); discasame =&gt; n(call),Dial(${DIAL},60,TWXr)same =&gt; n,Hangup()



ATENÇÃO: É importante que este plano de discagem seja implementado em ambos servidores para que possamos garantir que não sejam recebidas e nem realizadas mais ligações do que o valor limite.



Agora é com você. Adapte e estenda este plano de discagem e se quiser compartilhar suas melhorias, fique à vontade para postá-las nos comentários.




Até a próxima.