sábado, 5 de outubro de 2019

Plataforma Exchange (VoIP Peering) - como funciona?


As populares Plataformas VoIP Peering ou Plataformas Exchange podem voltar em um novo formato.

As plataformas VoIP Peering ou Exchange eram bastante populares há alguns anos e, desde então, tivemos um declínio na popularidade delas. No entanto, com o surgimento de novas tecnologias e condições de mercado, essas plataformas poderão ter seu retorno garantido, de uma, ou de outra forma. Vamos ver o que são e como funcionam.

Com o crescimento da popularidade do VoIP no início dos anos 2000, houve um grande aumento no número de operadoras de VoIP independentes (ITSP) em todo o mundo. Havia (e existem) muitos provedores de rotas diretas e muitos atacadistas ou agregadores, bem como varejistas. Os provedores de rotas diretas tentaram interconectar-se diretamente com os varejistas para vender seus produtos, mas como o número de destinos é muito grande, em muitos casos isso levou a um alto número de conexões e contratos ponto a ponto que se tornaram difíceis de gerenciar. Portanto, muitos varejistas utilizaram poucos provedores de rotas diretas para as rotas mais importantes e atacadistas para o restante tráfego. Esta solução funciona em geral, mas em um ambiente muito competitivo não garante os melhores preços e qualidade. Novos fornecedores de rotas diretas apareciam todos os dias, e eles também estavam procurando acesso a compradores que eram difíceis de obter.

Uma das respostas para esse problema foi Trocas (Exchanges). As trocas (Exchanges) possibilitaram que os vendedores oferecessem suas rotas na plataforma de mercado aberto e os compradores procurassem as melhores ofertas. As trocas também levaram a maior parte do trabalho de teste, verificação e compensação financeira para os compradores. Aqui está um exemplo de como o Exchange procura a perspectiva do comprador/vendedor:

Os compradores, com sua capacidade espacial, entraram em contato com a Exchange e ofereceram suas rotas. O Exchange testaria suas rotas quanto à validade, manualmente ou através de algum processo automático. Após os testes, o contrato entre a Exchange e o Vendedor foi assinado, onde o vendedor estava vendendo suas rotas para a Exchange e a troca garante o pagamento. Em seguida, a rota é publicada na plataforma de negociação, sem mencionar os detalhes do vendedor. Em vez disso, foi atribuído algum tipo de número de identificação.

Os compradores, por sua vez, assinariam o contrato com a Bolsa e obteriam acesso à plataforma de negociação da Bolsa. Eles podem ver o preço anunciado das rotas e as estatísticas existentes, como ASR e ACD, e capacidade. Quando decidem comprar a rota, fazem os lances para comprá-la. dependendo do contrato, eles podem ser solicitados a pagar um depósito antes de obter acesso total. Uma vez que o acesso é concedido, os compradores podem começar a enviar seu tráfego para a bolsa e os vendedores aceitando a troca. O tráfego é roteado e cobrado por Exchange com ambas as partes, ou seja, não há transações diretas entre vendedor e comprador, mas o faturamento é liquidado entre a Exchange e o comprador ou/e a Exchange e o vendedor.

As trocas foram bastante populares no início dos anos 2000, sem dúvida a maior delas foi a Arbinet Thexchange, que foi adquirida pela Primus Telecommunications em 2010. Havia também uma série de outras menores, que forneciam acesso a operadoras menores que não podiam acessar os serviços da Arbinet devido a altas taxas de acesso.
Tecnicamente, as trocas tinham alguns detalhes específicos, alguns dos quais eu gostaria de listar abaixo:
  • A maioria era anônima, ou seja, o tráfego passava por equipamentos capazes de ocultar endereços IP das partes, como um SBC (no conceito de Controlador da Borda da Sessão, e não como o conceito de um Firewall para SIP);
  • Havia mecanismos automáticos de classificação de qualidade de rota em funcionamento que podiam medir parâmetros de qualidade de rota como ASR e/ou ACD;
  • As Exchanges podem oferecer algum meio de "classificar" as rotas para os usuários (como os botões de CURTIR nas redes sociais) - para que outros compradores possam optar por usar apenas rotas com determinadas classificações positivas;
  • Mecanismo de licitação: para as rotas com capacidade limitada, o licitante mais alto receberá um roteamento de prioridade mais alta.

Hoje, as bolsas de VoIP (VoIP Peering Exchanges) perderam sua posição no mercado, mas isso não necessariamente significa que elas não podem retornar de uma ou outra forma. Novas tecnologias podem ajudá-los a retornar. Um dos problemas que impediu que as Exchanges (trocas) se tornassem amplamente usadas foi a falta de confiança: e vemos o Blockchain como uma solução possível para resolver o problema de confiança. O uso de Blockchain no VoIP em geral foi discutido anteriormente, especialmente como um banco de dados descentralizado: é isso que as Exchanges (trocas) realmente são.

Por Aivís Olsteins.

sexta-feira, 4 de outubro de 2019

Asterisk® SCF™ - Dialplan modular

Este é apenas um sumário de um Dialplan no Asterisk® SCF™ implementado a alguns anos, espero que você ache ele tão útil quanto eu achei.

A necessidade surgiu quando administrava em Londrina/PR uma rede, com quatro servidores Asterisk® SCF™, referente a Matriz e Filiais interconectadas e integrada a um pequeno Call Center (interno para SAC), o problema era manter quatro Dialplan separados, o que acabou sendo um esforço cansativo. Este conceito é um FORK de uma ideia de um profissional (Amit Mehta) de Sydney/Australian via e-mail.

Os objetivos deste Dialplan foi o seguinte:
  • Modularize todas as tarefas rotineiras que são executadas no plano de discagem.
  • Redução substancialmente da quantidade geral e a repetição de código no Dialplan.
  • Reduçao da sobrecarga de gerenciamento do Dialplan.
  • Tornar a depuração do Dialplan fácil para entendimento e o mais importante, legível.
  • Otimizar o uso de variáveis ​​globais e de canal para reduzir a quantidade e os locais de futuras alterações no Dialplan.
  • Atualizar o Dialplan da sintaxe do Asterisk® SCF™ v1.4 para Asterisk® SCF™ v11.
    • Ex.: Converter todas as Macros e Sub-Rotinas.
    • Incorporar o uso de Sub-Rotinas com a capacidade de passar variáveis ​​através do comando "Gosub".
Muito semelhante à versão padrão da extensions.conf no Asterisk® SCF™ v11, com algumas pequenas personalizações para as variáveis passadas para ele. Tecnicamente, não é isso que estou chamando de "modular" (que na verdade é uma Sub-Rotina); este é apenas um exemplo do contexto stdexten que alguns podem achar útil.

No meu cenário, sob nenhuma circunstância haveria motivo para alterar o contexto do correio de voz; portanto, os argumentos passados são: Os dispositivos para tocar, o período de tempo limite (por quanto tempo tocar o ramal) e a caixa de correio de voz de destino. Se nenhum dos segundo e terceiro argumentos forem passados, ele assumirá um período de tempo limite de 25 milissegundos e a extensão passada no argumento um como caixa de correio de voz.

Aqui está o contexto stdexten:
[stdexten]
; Standard extension subroutine:
; ${EXTEN} - Extension ; ${ext}
; ${ARG1} - Device(s) to ring ; ${dst}
; ${ARG2} - Dial Timeout ; ${tmt} 25 seconds
; ${ARG3} - Specify voicemail box to use ; ${mbx}
; Syntax: Gosub(context,extension,priority(${ARG1},${ARG2},${ARG3}))
; Use: Gosub(stdexten,${EXTEN} or specify extension,stdexten(SIP/4000&SIP/4002,25,4000))
exten => _X.,1001(stdexten),NoOp(Dialing standard extension)
exten => _X.,n,Set(LOCAL(ext)=${EXTEN})
exten => _X.,n,Set(LOCAL(dst)=${ARG1})
exten => _X.,n,Set(LOCAL(tmt)=${IF($[${ISNULL(${ARG2})} = 1]?25:${ARG2})})
exten => _X.,n,Set(LOCAL(mbx)=${IF($[${ISNULL(${ARG3})} = 1]?${ext}:${ARG3})})
exten => _X.,n,Dial(${dst},${tmt})
exten => _X.,n,Goto(stdexten-${DIALSTATUS},1)

exten => stdexten-NOANSWER,1,Voicemail(${mbx},u)
exten => stdexten-NOANSWER,n,Return()

exten => stdexten-BUSY,1,Voicemail(${mbx},b)
exten => stdexten-BUSY,n,Return()

exten => _stde[x]te[n]-.,1,Goto(stdexten-NOANSWER,1)

exten => a,1,VoicemailMain(${mbx})
exten => a,n,Return()
Aqui está um exemplo simples de uma chamada interna para o stdexten que também incorpora o uso de outro módulo do Dialplan, o "sub-GetSourceCID", para procurar primeiro o identificador de chamadas de origem no banco de dados MySQL do Asterisk® SCF™:

exten => _40XX,1,Gosub(sub-GetSourceCID,${EXTEN},1)
exten => _40XX,n,Gosub(stdexten,${EXTEN},stdexten(SIP/${EXTEN}))
exten => _40XX,n,Hangup()
Bom seria isto, em um futuro post, vou mostrar como migrei este contexto para AEL, e posteriormente para LUA.

Agradecimento ao amigo Amit Mehta.

Bash Script - Registre chamadas simultâneas do Asterisk® SCF™ para o MySQL e outras informações úteis

Aqui está um script em bash rápido, a ideia é registrar as chamadas simultâneas de cada um dos meus troncos de longa distância (DDD) do Asterisk® SCF™ em um banco de dados MySQL para poder analisar rapidamente as tendências de uso. Certamente, provavelmente existem outros softwares de código aberto por aí que podem fazer isso e fornecer gráficos muito pequenos ou não (cdr-stats ou asternic me vêm à mente). mas qual é a graça nisso? Como mencionei, o script é extremamente primitivo (apenas o mínimo necessário, pois não tinha muito tempo para gastar nele) e não contém nenhuma verificação de erro, mas também pode ser usado como uma ideia de informações úteis para suar o Grafana.

Mostrar todas as chamadas SIP ativas em um único tronco
rasterisk -x "core show channels verbose" | grep "^SIP/yourSIPTrunkName-"
Mostrar número simultâneo de chamadas SIP em um único tronco
rasterisk -x "core show channels verbose" | grep -c "^SIP/yourSIPTrunkName-"
Mostrar todas as chamadas DAHDI ativas nos canais 1-24
rasterisk -x "core show channels verbose" | grep "^DAHDI/[1-9]-1\|^DAHDI/1[0-9]-1\|^DAHDI/2[0-4]-1"
Mostrar número simultâneo de chamadas DAHDI nos canais 1-24
rasterisk -x "core show channels verbose" | grep -c "^DAHDI/[1-9]-1\|^DAHDI/1[0-9]-1\|^DAHDI/2[0-4]-1"
Para uma exibição útil em tempo real de chamadas simultâneas em um único tronco, incorpore o comando watch
watch -n .5 'rasterisk -x "core show channels verbose" | grep "^SIP/yourSIPTrunkName-"'
Como observação, sinta-se à vontade para usar o script abaixo, se quiser, mas você terá que escrever suas próprias expressões regulares para corresponder aos canais DAHDI usados em seu ambiente específico.

Você também precisará de um banco de dados MySQL em algum lugar para inserir os dados. Neste exemplo, eu nomeei a tabela “trunkusage” e ela possui quatro colunas.

Os tipos de dados são os seguintes:
  • ID – int 11 unsigned auto-increment
  • time – datetime
  • trunk – varchar 50
  • activecalls – int 11 unsigned
Para rodar como um daemon, crie o Shell Script em /etc/init.d/trunkusage e certifique-se de executar chmod + x, assim como executar o update-rc.d para permitir os níveis de execução padrão.

#!/bin/bash
#
# Log Concurrent Calls to MySQL
#
DBUSER='yourMysqlUser';
DBPASS='yourMysqlPass';
DBHOST='yourMysqlServer';
DBNAME='yourMysqlDatabaseName';
TBLNAME='trunkusage';
TRUNKNAME=('mySIPProvider1' 'mySIPProvider2' 'dahdiCircuitProvider');
TRUNKTYPE=('SIP' 'SIP' 'DAHDI');
RUNTIME='5';  # how often to run in seconds

while true  # Infinite loop
do
        i=0
        for trunk in "${TRUNKNAME[@]}" ; do
                unset ACTIVECALLS;
                if [ "${TRUNKTYPE[$i]}" == "SIP" ] ; then
                        ACTIVECALLS=$( /usr/sbin/asterisk -x "core show channels verbose" | grep -c "^${TRUNKTYPE[$i]}/${trunk}-" ) > /dev/null 2>&1;
                        mysql -u ${DBUSER} -p${DBPASS} -h ${DBHOST} ${DBNAME} -e "INSERT INTO ${TBLNAME} (time,trunk,activecalls) VALUES (NOW(), '${trunk}', '${ACTIVECALLS}');" > /dev/null 2>&1;
                        ((i++));
                elif [ "${TRUNKTYPE[$i]}" == "DAHDI" ] ; then
                        # Regex pattern for channels 1-24
                        ACTIVECALLS=$( /usr/sbin/asterisk -x "core show channels verbose" | grep -c "^${TRUNKTYPE[$i]}/[1-9]-1\|^${TRUNKTYPE[$i]}/1[0-9]-1\|^${TRUNKTYPE[$i]}/2[0-4]-1" ) > /dev/null 2>&1;
                        mysql -u ${DBUSER} -p${DBPASS} -h ${DBHOST} ${DBNAME} -e "INSERT INTO ${TBLNAME} (time,trunk,activecalls) VALUES (NOW(), '${trunk}', '${ACTIVECALLS}');" > /dev/null 2>&1;
                        ((i++));
                fi
        done
        sleep ${RUNTIME};
done