Do meu antigo blog, só atualizando por aqui!
Recebi na lista do PostgreSQL uma mensagem indicando esse site. Achei muito bom e quis compartilhar.
Sempre é bom dar risada de alguns problemas, principalmente quando se trata de banco de dados!
Do meu antigo blog, só atualizando por aqui!
Recebi na lista do PostgreSQL uma mensagem indicando esse site. Achei muito bom e quis compartilhar.
Sempre é bom dar risada de alguns problemas, principalmente quando se trata de banco de dados!
É… passei um bom tempo sem postar aqui, mas pretendo me empenhar novamente.
Começarei a fazer alguns posts sobre desvios no Asterisk.
As centrais convencionais possuem variados tipos de desvios. Os mais comuns são: desvio imediato, desvio condicional, desvio se ocupado e desvio se não houver resposta. Serão o total de três posts, dois descrevendo cada um dos desvios e o terceiro com um contexto para cancelar todos os desvios, verificar desvios ativos, e o plano de discagem para verificar antes de discar para o ramal .
Hoje irei comentar sobre a facilidade de desvio imediato, desvio se ocupado e desvio se não houver resposta.
O desvio imediato é uma facilidade onde o usuário do ramal “A” digita um código + o número do ramal “B”. Quando este código for ativo, toda vez que alguém ligar para o ramal “A” a ligação será desviada e chamará no ramal “B”, sem ao menos tentar chamar o ramal “A”.
O desvio se ocupado funciona quase igual, a única funcionamento que muda é que o desvio só é utilizado quando o ramal está ocupado e o desvio se não houver resposta é quando o ramal chama e estoura o tempo chamando, assim é utilizado o desvio para o ramal desejado.
O contexto “desvio-imediato” servirá para ativar/desativar o mesmo. Para utilizarmos a facilidade de desvio, será usado o AstDB, pela questão de ter o acesso fácil via dialplan.
[desvio-imediato]
exten => *50,1,Answer(1)
exten => *50,2,Set(EXISTE=${DB_EXISTS(DesvioImediato/${CALLERID(num)})})
exten => *50,3,GotoIf($["${EXISTE}" = "0"]?continua:desliga)
exten => *50,4(continua),Playback(ramal)
exten => *50,5,Read(RAMAL,,4,,,)
exten => *50,6,Set(DB(DesvioImediato/${CALLERID(num)})=${RAMAL})
exten => *50,7,Playback(desvio-ativo)
exten => *50,8,Goto(desvio-imediato,h,1)
exten => *50,9(desliga),Playback(desvio-existente)
exten => *50,10,Goto(desvio-imediato,h,1)
exten => *51,1,Answer(1)
exten => *51,2,Set(RAMAL=${DB_EXISTS(DesvioImediato/${CALLERID(num)})
exten => *51,3,GotoIf($["${RAMAL}" = "1"]?continua:desliga)
exten => *51,4(continua),Noop(DB_DELETE(DesvioImediato/${CALLERID(num)}))
exten => *51,5,Playback(desvio-cancelado)
exten => *51,6,Goto(desvio-imediato,h,1)
exten => *51,7(desliga),Playback(desvio-nao-existe)
exten => *51,8,Goto(desvio-imediato,h,1)
exten => i,1,Goto(desvio-imediato,h,1)
exten => h,1,HangUp()
O código *50 serve para ativar o desvio. Quando o usuário discar o código para ativar, o Asterisk irá atendê-lo após 1 segundo (parâmetro 1 na app Answer()) e irá verificar na tabela do AstDB se existe a família “Desvio” com a chave “${CALLERID(num)}” (o número do ramal que está chamando a facilidade). Se houver a chave indicada, ele envia o chamador para desvio-imediato,*50,8, onde será executado um playback informando que já existe um desvio ativo e será enviado para a extensão desvio-imediato,h,1, onde será esecutado um HangUp(). Se não houver a chave indicada, será direciona para a tag continua, onde será executado um áudio solicitando para entrar com um número de ramal, será lido o número do ramal com a opção Read() e será inserido no AstDB o número do ramal. Após isso será executado um áudio informando que o desvio foi ativo e irá desligar o canal.
O código *51 serve para desativar o desvio. Quando o usuário discar o código, o Asterisk irá atender a ligação, verificar se o desvio existe no AstDB, se existir o Asterisk irá deletar e tocar um áudio informando que o desvio foi desativado, se não existir o Asterisk irá somente informar que não existe desvio imediato ativo.
Agora, o desvio se ocupado e o desvio se não houver resposta funcionam exatamente iguai a esse. Porém cada um deve possuir sua extensão para ativar/desativar e sua própria família no AstDB.
Segue o extensions.conf completo:
[desvios]
include => desvio-imediato
include => desvio-ocupado
include => desvio-timeout
[desvio-imediato]
exten => *50,1,Answer(1)
exten => *50,2,Set(EXISTE=${DB_EXISTS(DesvioImediato/${CALLERID(num)})})
exten => *50,3,GotoIf($["${EXISTE}" = "0"]?continua:desliga)
exten => *50,4(continua),Playback(ramal)
exten => *50,5,Read(RAMAL,,4,,,)
exten => *50,6,Set(DB(DesvioImediato/${CALLERID(num)})=${RAMAL})
exten => *50,7,Playback(desvio-ativo)
exten => *50,8,Goto(desvio-imediato,h,1)
exten => *50,9(desliga),Playback(desvio-existente)
exten => *50,10,Goto(desvio-imediato,h,1)
exten => *51,1,Answer(1)
exten => *51,2,Set(RAMAL=${DB_EXISTS(DesvioImediato/${CALLERID(num)})
exten => *51,3,GotoIf($["${RAMAL}" = "1"]?continua:desliga)
exten => *51,4(continua),Noop(DB_DELETE(DesvioImediato/${CALLERID(num)}))
exten => *51,5,Playback(desvio-cancelado)
exten => *51,6,Goto(desvio-imediato,h,1)
exten => *51,7(desliga),Playback(desvio-nao-existe)
exten => *51,8,Goto(desvio-imediato,h,1)
exten => i,1,Goto(desvio-imediato,h,1)
exten => h,1,HangUp()
[desvio-ocupado]
exten => *52,1,Answer(1)
exten => *52,2,Set(EXISTE=${DB_EXISTS(DesvioOcupado/${CALLERID(num)})})
exten => *52,3,GotoIf($["${EXISTE}" = "0"]?continua:desliga)
exten => *52,4(continua),Playback(ramal)
exten => *52,5,Read(RAMAL,,4,,,)
exten => *52,6,Set(DB(DesvioOcupado/${CALLERID(num)})=${RAMAL})
exten => *52,7,Playback(desvio-ativo)
exten => *52,8,Goto(desvio-ocupado,h,1)
exten => *52,9(desliga),Playback(desvio-existente)
exten => *52,10,Goto(desvio-ocupado,h,1)
exten => *53,1,Answer(1)
exten => *53,2,Set(RAMAL=${DB_EXISTS(DesvioOcupado/${CALLERID(num)})
exten => *53,3,GotoIf($["${RAMAL}" = "1"]?continua:desliga)
exten => *53,4(continua),Noop(DB_DELETE(DesvioOcupado/${CALLERID(num)}))
exten => *53,5,Playback(desvio-cancelado)
exten => *53,6,Goto(desvio-ocupado,h,1)
exten => *53,7(desliga),Playback(desvio-nao-existe)
exten => *53,8,Goto(desvio-ocupado,h,1)
exten => i,1,Goto(desvio-ocupado,h,1)
exten => h,1,HangUp()
[desvio-timeout]
exten => *54,1,Answer(1)
exten => *54,2,Set(EXISTE=${DB_EXISTS(DesvioTimeout/${CALLERID(num)})})
exten => *54,3,GotoIf($["${EXISTE}" = "0"]?continua:desliga)
exten => *54,4(continua),Playback(ramal)
exten => *54,5,Read(RAMAL,,4,,,)
exten => *54,6,Set(DB(DesvioTimeout/${CALLERID(num)})=${RAMAL})
exten => *54,7(volta),Playback(toques)
exten => *54,8,Read(NUM,,1,,,)
exten => *54,9,ExecIf($["${NUM}" = "0"]?Playback(opcao-invalida))
exten => *54,10,GotoIf($["${NUM}" = "0"]?volta)
exten => *54,11,Set(RING=${MATH(${NUM}*4,int)})
exten => *54,12,Set(DB(DesvioTimeoutTempo/${CALLERID(num)})=${RING})
exten => *54,13,Playback(desvio-ativo)
exten => *54,14,Goto(desvio-timeout,h,1)
exten => *54,15(desliga),Playback(desvio-existente)
exten => *54,16,Goto(desvio-timeout,h,1)
exten => *55,1,Answer(1)
exten => *55,2,Set(RAMAL=${DB_EXISTS(DesvioTimeout/${CALLERID(num)})
exten => *55,3,GotoIf($["${RAMAL}" = "1"]?continua:desliga)
exten => *55,4(continua),Noop(DB_DELETE(DesvioTimeout/${CALLERID(num)}))
exten => *55,5,Noop(DB_DELETE(DesvioTimeoutTempo/${CALLERID(num)}))
exten => *55,6,Playback(desvio-cancelado)
exten => *55,7,Goto(desvio-timeout,h,1)
exten => *55,8(desliga),Playback(desvio-nao-existe)
exten => *55,9,Goto(desvio-timeout,h,1)
exten => i,1,Goto(desvio-timeout,h,1)
exten => h,1,HangUp()
Note que o desvio se não houver resposta chama algumas aplicações à mais. Na extensão *54, prioridade 7, ele executa um áudio informando para entrar com o número de vezes que o ramal será chamado antes de desviar. Após ler o número de 1 dígito (de 1 à 9, se for zero ele irá executar um áudio informando que a opção é inválida e retornar para solicitar novamente o número), ele irá multiplar o mesmo por 4 (cada toque é quatro segundos, o Asterisk chama por segundos, portanto…) e salvar no AstDB. Na extensão *55, prioridade 5, o número de toques será deletado do AstDB.
Nota:
Bom, esses desvios foram simples, o problema será o desvio condicional!
Até mais!
Servidor1: ip = 192.168.0.1/24 Servidor2: ip = 192.168.0.2/24
OBS1.: Todas as configurações mostradas serão realizadas no servidor1. Para o servidor2 será igual, só invertendo os campos definidos. Exemplo: Quando apontar para o ip do servidor2, a configuração do servidor2 irá apontar para o ip do servidor1 e assim por diante.
No último artigo descrevi um pouco da história do DUNDi, neste colocarei as configurações. Vamos começar com o entroncamento IAX2 entre os servidores.
#cd /etc/asterisk/ #vim iax2.conf
Dentro do arquivo crie ( crtl+c / crtl+v :p ):
[dundi] type=friend dbsecret=dundi/secret context=entradaDUNDi
O parâmetro “dbsecret” é a senha usada pelo DUNDi, o “dundi/secret” é a senha do DUNDi no AstDB. Ele gerará uma nova à cada hora. Você pode checar no console do asterisk com o comando:
Asterisk*CLI> database show
Agora vamos partir para o dundi.conf. Neste arquivo você setará as relações entre servidores e suas respectivas respostas. O DUNDi usa sua própria porta de comunicação e troca de mensagens. Esta porta é a UDP 4520. As ligações serão transportadas pelo canal IAX2, ou seja, a comunicação do DUNDi e as ligações não são transportadas juntas. Vamos ao arquivo do servidor1:
# vim dundi.conf [general] department=Departamento da empresa organization=Nome da Empresa locality=Cidade stateprov=Estado country=País email=Seu email phone=Seu telefone
What hell??? Para o que servirá isso? Simples! Da mesma forma que você pode utilizar o DUNDi localmente entre dois servidores, você poderá criar uma super ultra mega rede com o DUNDi. Imagine que você tenha 10 servidores interligados via DUNDi? Essas configurações irão ajudá-lo a interpretar as comunicações entre os servidores (saber quem tá enviando e recebendo requisições.) e saber em qual você está mexendo. Isso é muito utilizado em configurações de roteadores (de uma forma diferente é claro).
;bindaddr=0.0.0.0
;port=4520
entityid=00:B0:D0:CC:5C:E8 ;Coloque o mac-address de sua NIC aqui. Por default ele pegará a primeira placa configurada.
cachetime=5 ;Define o tempo de validade de uma consulta DUNDi. Serve para evitar loops infinitos de consulta.
ttl=2 ;Define o número de saltos que o pedido DUNDi pode possuir antes de ser descartado.
autokill=yes ;Define o que acontece quando um ACK não é recebido depois de 2 segundos. No caso de “yes” ele derruba a chamada.
[mappings]
dundi=>dundiExtens,0,IAX2,dundi:${SECRET}@192.168.0.1/${NUMBER},nopartial
O mapeamento segue a seguinte sintaxe:
dundiContext => dundiExtens,peso,tecnologia,destino[,opções]
dundiContext: Nome do contexto utilizado pelo DUNDi em suas consultas.
dundiExtens: Nome do contexto que o DUNDi verificará se o ramal existe.
peso: É o peso para resposta de verificação. Quanto menor o valor, maior prioridade.
tecnologia: Tecnologia do ramal desejado. Ex.: SIP.
destino: Define o destino para encontrar o ramal desejado.
opções: São opções para o mapeamento. No caso foi definido “nopartial” (Sem parcial), ou seja, o DUNDi só proverá a resposta se o requisição bater exatamente com as extensões que ele possui.
[00:B0:D0:CB:80:7A] ;Mac do servidor2 model = symmetric host = 192.168.0.2 ;IP do servidor2 inkey = dundi outkey = dundi include = priv permit = priv qualify = yes order = primary
Os servidores usarão a mesma chave (inkey e outkey). Para gerar as chaves:
#cd /var/lib/asterisk/keys #astgenkey -n priv
O comando irá criar dois novos arquivos neste diretório que são: priv.key e priv.pub. Agora copie as duas chaves para o sevidor2.
IMPORTANTE: insira a linha “regexten=dundiExtens” no generals do sip.conf. Com essa linha o ramal sip que se logar irá inserir uma extensão no contexto dundiExtens. Assim quando o DUNDi for procurar pela extensão no dundiExtens, ela estará lá!
Vamos configurar o extensions.conf do servidor1:
#vim extensions.conf
[ramais] ;Contexto dos seus ramais internos.
exten => _8XXX,1,ChanIsAvail(SIP/${EXTEN})
;Checa se o ramal está registrado.
exten => _8XXX,2,GotoIf( $[ "${AVAILCHAN}" = "5" ]?dundi:disca)
;AVAILCHAN = 5 significa que o ramal está UNAVALIABLE (não está registrado).
exten => _8XXX,3(disca),Dial(SIP/${EXTEN},120,Ttr)
exten => _8XXX,4,Hangup()
exten => _8XXX,5(dundi),Goto(dundiLookup,${EXTEN},1
exten => _8XXX,6,Hangup()
[dundiLookup] ;Envia a requisição para o DUNDi.
switch => DUNDi/dundi
[dundiExtens] ;Quando os ramais se registrarem serão inseridos aqui.
[entradaDundi] ;Configurado no tronco IAX2.
exten => _8XXX,1,Goto(ramais,${EXTEN},1)
Salve o arquivo e entre no console do Asterisk.
Asterisk*>reload
Agora é só realizar as configurações no servidor2!
OBS2.: Os módulos usados à principio carregam automaticamente com o Asterisk. Caso não ocorra, abra o arquivo /etc/asterisk/modules.conf e insira as seguintes linhas:
load => pbx_dundi.so load => res_crypto.so load => app_chanisavail.so
OBS3.: As configurações aqui foram realizadas no Asterisk versão 1.6.0.24. Portanto, se você usa outra versão, leia os samples dos arquivos para realizar as modificações necessárias para sua versão.
Acho que é isso! Caso não consigam configurar é só me mandar um e-mail ou deixar um comentário.
Obs.: Alguns trechos do artigo foram retirados dos links no final da página. Quanto às configurações, eu realizei e testei.
Repostando um post do antigo blog.
Este artigo é sobre o “protocolo de rotamento DUNDi”, esse que vem integrado com o Asterisk desde os primórdios (desde a versão 1.0). Este artigo é dividido em duas partes, a primeira com uma explicação do que é o DUNDi e como funciona basicamente. A segunda parte abrangerá as configurações.
Como foi colocado acima, o DUNDi não é um procolo VoIP e sim um sistema p2p (peer-to-peer) para rotear chamadas VoIP entre serviços de telefonia, sendo as chamadas realizadas por protocolos padrões, tais como IAX, SIP, H323. O DUNDi pode ser usado para criar um servidor de comunicação (ele pode ser usado tanto para gateways VoIP quanto para Asterisk ou integrar os dois via VoIP) sem pontos centrais de falha e, arbitrariamente, qualquer mudança de extensões, falhas e adições na sua rede são automaticamente absorvidas para dentro da nuvem sem nenhuma configuração adicional, ficando assim transparente para o usuário.
Com o surgimento da tecnologia VoIP surgiu junto um grande problema. Como rotear as ligações entre a PSTN¹ e a internet? Para isso -em meados de 1997- a ITU-T² criou um padrão chamado ENUM. O padrão ENUM³ é basicamente a convergência de ligações da PSTN para a rede de protocolos da internet (IP). Em uma forma simplificada, o ENUM é o padrão criado para mapear os números de uma operadora VoIP para seu respectivo nome de domínio (DNS). Por causa dele nós podemos ligar de uma linha analógica ou digital para uma linha VoIP, fantástico não é? Não irei me aprofundar no assunto, pois tem muita coisa e acabaremos perdendo o foco, mas se quiserem ler mais sobre o assunto tem algumas referências abaixo (ou pesquisem sobre ENUM, RFC3761 e E.164). Baseado no ENUM, Mark Spencer criou um protocolo mais flexível e descentralizado e chamou seu novo filho de DUNDi (Distributed Universal Number Discovery). Vamos começar com uma explicação básica de funcionamento:
Extensões:
Servidor1 >> 8XXX Servidor2 >> 8XXX
O ramal 8026 está logado no servidor1 e quer discar para o ramal 8101, então o servidor1 checará se o ramal está logado. Porém ramal não está logado no servidor1. E agora José? O servidor1 irá solicitar para o DUNDi verificar se a extensão está logada nas rotas conhecidas. Então ele envia uma requisição para o servidor2 e ele responde: “Ow yeah baby, esta extensão está logada aqui. Para alcançá-la utlize: IAX2/user:pass@servidor2/8101″. O servidor1 encaminha a ligação para o destino que o servidor2 recomendou! É assim que funfa o DUNDi! Muito mais fácil do que imaginavam, não é?
Vamos supor que o ramal 8026 quer chamar novamente o ramal 8101, porém o ramal 8101 não está registrado em nenhum dos dois servidores! Então o servidor1 realizará os mesmo procedimentos anteriores. Checa internamente se o ramal está logado e não o encontra logado, então ele envia a requisição para o servidor2, porém o servidor2 responde que não encontrou o ramal logado. Sendo assim o servidor2 envia uma resposta negativa para o servidor1. Quando o servidor1 receber a resposta do servidor2 ele enviará uma resposta de “not found” para o ramal 8026, que será convertida no famoso tutu (tom de ocupado).
Na próxima parte colocarei as configurações básicas e estarei postando provavelmente manhã à noite ou sábado.
[1] http://www.normes-internet.com/normes.php?rfc=rfc3761&lang=pt
[2] http://www.enum.org/what.html
[3] http://www.dundi.com/
[4] http://en.wikipedia.org/wiki/E.164
¹ PSTN é a nuvem de telefonia pública (Public switched telephone network).
² ITU-T é uma agência intergovernamental que cria referências para o setor de telecomunicações.(Telecommunication Standardization Sector).
³ ENUM é um nome para o título RFC3761. Existe também o RFC2916 que é a versão obsoleta do ENUM atual.
Boa tarde pessoal.
Seguinte, meu amigo Wagner me pediu que eu comentasse sobre algumas vantagens do FS sobre o Asterisk. Pelo pouco que eu estudei até o momento, vou colocar minha opinião:
Acredito que as principais vantagens do FS vs. Asterisk são três. Segue:
1ª – Os principais módulos do Asterisk são linkados diretamente no core do mesmo (isso é mais feio do que bater em mãe…). Se algum módulo não estiver presente ou estiver corrompido, o Asterisk não sobe. Já no FS, o core não depende dos módulos externos. A arquitetura do FS foi criada com o máximo de cuidado, tudo isso para evitar os deadlocks e outros problemas que nós (administradores do Asterisk) enfrentamos muito.
2ª – Toda ligação/canal criado no FS possui sua própria Thread. Fim.
3ª – Escalabilidade. Você pode encontrar inúmeros testes na internet sobre Asterisk vs. FS. Em todos, você terá comparações parecidas sobre uma máquina rodando Asterisk e outra igual rodando FS e será fácil de notar de notar as diferenças. A principal diferença nos testes é o número de ligações simultâneas. O FS consegue fazer em torno de 4 à 5 vezes mais ligações simultâneas que o Asterisk. Este é um ponto extremamente forte.
Links:
Nota:
Bom, com o tempo vou completando e corrigindo algo (se houver algum erro).
At, Rodrigo Lang.
Neste exato momento estou migrando um servidor remotamente (isso mesmo, às 2 da manhã…).
Tudo ocorria perfeitamente, até que, em um certo momento o MySQL do servidor fez a Egipícia e não quis aceitar nenhum tipo de conexão…
Vejam bem, nunca me referi ao MySQL como banco de dados… ;p
Por favor, aprendam Como fazer perguntas inteligentes!!!