Recibiendo datos de la calidad del audio tras una llamada

A menudo (o siempre) es interesante recibir datos sobre la calidad de audio de una llamada que ha procesado nuestro Asterisk. Hablamos del Jitter, PacketLoss, MOS (Mean Opinion Score)… Aunque hay otras opciones como utilizar los RTCP Stats de Asterisk (Mejorado a partir de 1.6, pero en desuso) donde se establecen variables de canal con los datos de la calidad de audio de la llamada, hoy vamos a probar las opciones que nos dan los propios terminales SIP (¡Inteligencia en los terminales!).

Las últimas versiones del firmware de Cisco para sus terminales Spa5xx (+7.4.7), nos permiten configurar un parámetro con el que podremos enviar toda la información relativa a la calidad del audio a un servidor tras finalizar una llamada (Terminales Snom con firmware +v8 parece que también lo soportan, pero no lo hemos probado). Se configura desde la propia web de forma muy sencilla:

Lo que hace el terminal en si es, enviar un mensaje SIP PUBLISH al servidor definido (P.Ej: collector@192.168.1.1:5060) conteniendo en el body datos relacionados de la llamada y la calidad de ésta.
Estos eventos están definidos en el RFC6035: Session Initiation Protocol Event Package for Voice Quality Reporting. Por si queréis echar un vistazo… ;P

Un ejemplo del mensaje que envía el terminal:

PUBLISH sip:collector@10.1.100.190:7060 SIP/2.0.
Via: SIP/2.0/UDP 10.10.0.180:5060;branch=z9hG4bK-e20d9c33.
From: <sip:terminalSIP@10.1.100.190>;tag=f23bbd323541b235.
To: <sip:terminalSIP@10.1.100.190>.
Call-ID: a01e12b6-6eb5ba81@10.10.0.180.
CSeq: 64175 PUBLISH.
Max-Forwards: 70.
Contact: <sip:terminalSIP@10.10.0.180:5060>.
Accept: application/sdp, message/sipfrag.
Event: vq-rtcpxr.
User-Agent: Cisco/SPA504G-7.4.7.
Content-Length: 802.
Content-Type: application/vq-rtcpxr.
.
VQSessionReport: CallTerm.
LocalMetrics:.
Timestamps:START=2011-5-11T11:20:18Z STOP=2011-5-11T11:20:19Z.
SessionDesc:PT=8 PD=PCMA SR=8000 FD=20 FO=8 FPP=10 PPS=100 PLC=3 SSUP=off.
CallID: e850c0fe-1e19aa0f@10.10.0.180.
FromID: <sip:terminalSIP@10.10.0.180:5060>.
ToID: <sip:5998@10.1.100.190:5060>.
OrigID: <sip:terminalSIP@10.10.0.180:5060>.
LocalAddr: IP=10.10.0.180 PORT=16824 SSRC=467580294.
LocalMAC: 00:02:fd:ff:d3:5a.
RemoteAddr: IP=10.1.100.190 PORT=13914 SSRC=510.
RemoteMAC: 0.
JitterBuffer:JBA=3 JBR=15 JBN=171 JBM=171 JBX=300.
PacketLoss:NLR=0 JDR=255.
BurstGapLoss:BLD=0 BD=0 GLD=0 GD=0 GMIN=16.
Delay:RTD=0 ESD=177 SOWD=88.
Signal:RERL=127.
QualityEst:RLQ=22 RCQ=20 MOSLQ=1.2 MOSCQ=1.2 QoEEstAlg=P.564.

DialogID:e850c0fe-1e19aa0f@10.10.0.180;to-tag=as0df6f540;from-tag=ea2ec326d50586bo0.

Si os fijáis, el servidor que recibe este PUBLISH está escuchando en el 5070 mientras la señalización de las llamadas (SIP) está en el puerto 5060. Sí, mientras Asterisk gestiona las llamadas necesitamos un OpenSIPS/Kamailio para gestionar estos PUBLISH.
¿Por qué?
Porque Asterisk hasta la versión 1.8 (quizá alguna versión de 1.6?¿) ni siquiera soportaba mensajes del tipo PUBLISH y a partir de la 1.8 los soporta pero no para estos eventos concretos (vq-rtcpxr). La respuesta de un Asterisk: :(

SIP/2.0 489 Bad Event.
Via: SIP/2.0/UDP 10.10.0.177:5061;branch=z9hG4bK-aea9a42c;received=10.10.0.177.
From: ;tag=11636c9b167e05fa.
To: ;tag=as0d04d7f8.
Call-ID: ae68d5ef-aadd8cb6@10.10.0.177.
CSeq: 1316 PUBLISH.
Server: "Irontec IVOZ".
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH.
Supported: replaces, timer.
Content-Length: 0.

A lo que vamos… vamos a configurar un OpenSIPS/Kamailio para recibir estos mensajes y hacer después con ellos lo que creamos oportuno (guardarlo en BBDD, ejecutar un script…).
No vamos a explicar como instalar el software ya que hay multitud de ‘HowTo’-s disponibles en la red. Vamos directamente a lo que nos interesa, el fichero de configuración. En este caso se ha utilizado OpenSIPS pero con Kamailio debería ser muy parecido si no igual. Es una instalación básica sin ningún módulo extra, ya que en este caso lo único que haremos será recibir los datos, ejecutar un script y responder con un OK.
Dialplan” de opensips.cfg:

####### Routing Logic ########

route{

if (!mf_process_maxfwd_header(“10″)) {

sl_send_reply(“483″,”Too Many Hops”);
exit;

}

if (!is_method(“PUBLISH”))  ## Solo gestionaremos PUBLISH
{

sl_send_reply(“503″,”Not here please”);
exit;

}
if (!uri==myself)
{

sl_send_reply(“503″,”SIP Publish ok, but please use our domain”);
exit;

}
if (is_method(“PUBLISH”))
{

if (!$(hdr(Event)[-1]) == “vq-rtcpxr”)  ## Solo gestionamos este evento concreto. Audio quality
{

sl_send_reply(“503″,”Not here please”);
exit;

}

xlog(“EVENT: $(hdr(Event)[-1])”);   ##Un poco de log…
xlog(“Got a PUBLISH: $rb”);

exec_avp(“/root/testing/test.sh ‘$rb’”);  ##Ejecutamos un Script pasándole como variable el body del PUBLISH recibido. También se puede utilizar la función exec_msg
sl_send_reply(“200″, “Thanks for this stats”);  ##Respondemos con un 200
exit;

}

}

Como se puede ver en los comentarios del código anterior, es posible utilizar, además de ‘exec_avp’, la función ‘exec_msg’. La diferencia es que, en un caso se procesa la salida del comando (exec_avp) y en el otro no (exec_msg). Detalle importante: la variable ‘$rb’ (reference to message body) tiene que pasarse al script entre comillas, porque el cuerpo del mensaje contiene caracteres especiales y necesitamos que nuestro script los pueda interpretar. Más info al respecto aquí y aquí.

¿Que podemos hacer en este script externo? Pues, todo lo que necesitemos/queramos y nuestra imaginación nos permita. Por ejemplo, sacar informes de calidad de audio de llamadas representando estos datos en gráficas creadas con RRDtool…

Happy VoIP hacking !!! ;P

Te ha gustado? Compartelo:
  • Print
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • BarraPunto
  • Meneame
  • Twitter

TLS+SRTP en Asterisk 1.8 (Especial Cisco SPA5xx)

Volvemos a la carga con un pequeño post sobre como configurar otra de las nuevas features que nos trae Asterisk 1.8: TLS y SRTP, audio (y video) cifrado y seguro.
Estos tests se han realizado con terminales Cisco SPA5XX, que supone tener que aplicar un pequeño parche en el código de Asterisk (luego veremos el porque), pero funciona exactamente igual para terminales Snom y softphones como Blink
La parte de configuración se explicará bastante rápido, ya que está explicado en varios sitios en la web.

Empezamos:
1. Es necesario compilar la librería libSRTP para que Asterisk tenga el soporte SRTP.

wget http://srtp.sourceforge.net/srtp-1.4.2.tgz
tar zxvf srtp-1.4.2.tgz
cd srtp/
CFLAGS="-Wall -O4 -fexpensive-optimizations -funroll-loops -fPIC" ./configure
make && make install

2. Descargamos y Compilamos Asterisk: (Para este Post se utiliza la versión 1.8.2.3)

svn co http://svn.asterisk.org/svn/asterisk/tags/1.8.2.3/ asterisk18
cd asterisk18
./configure
make menuselect (nos aseguramos de que esté res_srtp activado en 'Resource Modules')

**Ahora es cuando tenemos que aplicar el parche anteriormente mencionado**
¿Porque? Es necesario parchear el código porque los terminales SPA5xx envían dos líneas con el atributo crypto, tal que:

a=crypto:1 AES_CM_128_HMAC_SHA1_32 inline:Ud154Hz42jLai6YI7RBcKtctTHBzIKjiHM6nGD36.
a=crypto:2 AES_CM_128_HMAC_SHA1_80 inline:Ud154Hz42jLai6YI7RBcKtctTHBzIKjiHM6nGD36.

y Asterisk no es capaz de negociar cual de los métodos (AES_32 o AES_80) se va a utilizar para la encriptación. De hecho, sólo escoge el primero y como podéis ver, los Cisco envían primero el AES_32.
Aquí está el problema. Asterisk es capaz de manejar ambos tipos, pero sólo ofrece uno de ellos, el AES_80. Por tanto, tenemos que parchear el código para que Asterisk ofrezca en la señalización encriptación AES_32. Si no, se cifrará el Audio en las dos patas con un tipo diferente y nos quedamos sin audio y con un mensaje eterno (30 por Seg.) en el CLI:

WARNING[25205]: res_srtp.c:338 ast_srtp_unprotect: SRTP unprotect: authentication failure

Más info al respecto en el Bugtracker de Digium
Un poco de SIP para ver “claro” el problema (primer INVITE e INVITE de Asterisk al destino):

INVITE sip:200@10.10.0.165 SIP/2.0.
From: ;tag=630e30c1d5621880o3.
To: "200" .
m=audio 16890 RTP/SAVP 8 0 9 18.
a=crypto:1 AES_CM_128_HMAC_SHA1_32 inline:hE+4XPMbPaF9/XEgIek7rUJiqoTEpLGZ1YXNiJhS.
a=crypto:2 AES_CM_128_HMAC_SHA1_80 inline:hE+4XPMbPaF9/XEgIek7rUJiqoTEpLGZ1YXNiJhS.

INVITE sip:200@10.10.0.177:5063 SIP/2.0.
From: "100" ;tag=as72caceda.
To: .
Contact: .
User-Agent: Asterisk PBX 1.8.2.3.
Remote-Party-ID: "100" ;party=calling;privacy=off;screen=no.
m=audio 12202 RTP/SAVP 8.
a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:5uWtfxfK0vE90lTrgLTr83bRWTL2nCEFJ6NlXWjq.

El parche es bien simple:

--- channels/sip/sdp_crypto.c 2010-06-08 07:29:08.708826000 +0200
+++ channels/sip/sdp_crypto.c 2011-02-24 17:37:00.514711568 +0100
@@ -287,7 +287,8 @@
int sdp_crypto_offer(struct sdp_crypto *p)
{
char crypto_buf[128];
- const char *crypto_suite = "AES_CM_128_HMAC_SHA1_80"; /* Crypto offer */
+ //const char *crypto_suite = "AES_CM_128_HMAC_SHA1_80"; /* Crypto offer */
+ const char *crypto_suite = "AES_CM_128_HMAC_SHA1_32"; /* Crypto offer */

if (p->a_crypto) {
ast_free(p->a_crypto);

Aplicamos el parche (lo hemos nombrado como sdp_crypto.patch):

patch -p0 < sdp_crypto.patch (suponiendo que estamos en /usr/src/asterisk18 y tenemos el parche en la misma carpeta)

Asterisk is patched!!! :P
Ya podemos compilar e instalar:

make && make install

3. Configuración (tanto para TLS como para SRTP)
**TLS**
-Primero nos generamos una clave pública y otra privada, las fusionamos en un único fichero y la guardamos en algún sitio conocido.
Hay formas mucho mejores y elegantes de hacerlo (léeme), pero esto sólo es para testing! :P

openssl genrsa 1024 > host.key
openssl req -new -x509 -nodes -sha1 -days 365 -key host.key > host.cert
cat host.cert host.key > asterisk.pem
mv asterisk.pem /etc/asterisk/keys/

-Configuramos sip.conf para poder utilizar TLS:

tlsenable=yes
tlsbindaddr=0.0.0.0
tlscertfile=/etc/asterisk/keys/asterisk.pem

-Configuramos los peers para que trabajen con TLS. Tanto en realtime como en raw en sip.conf hay que añadir:

transport=tls (por defecto es UDP)

-Configuramos nuestro SPA5XX para que utilice TLS:

Ya tenemos señalización segura entre Asterisk y los terminales!! ;P
Para asegurarnos capturamos en el puerto 5061 y no vemos “nada”:

....J...F..Mg|.L^
...E}.....A...d.|.~...... l..i9.j,..q"..............&./....5................0..~0...................0...*.H........0..1.0...U....ES1.0...U....Vizcaya1.0...U....Erandio1.0...U.
..Irontec1.0...U....VozIP1.0...U....Irontec1 0...*.H........vozip@irontec.com0...110215125446Z..210212125446Z0..1.0...U....ES1.0...U....Vizcaya1.0...U....Erandio1.0...U.
..Irontec1.0...U....VozIP1.0...U....Irontec1 0...*.H........vozip@irontec.com0..0...*.H............0........>.S.51...bND.J..Q..O.).-t.."~x..g&^t....E.*..@..n.jF...v.t.<....Zf...%Y.......[...[....HE.e....9..8...qc..|(...P.....*.c4>.V..........0..0...U.........En?.0.%.^......
.0....U.#...0.......En?.0.%.^......
.......0..1.0...U....ES1.0...U....Vizcaya1.0...U....Erandio1.0...U.
..Irontec1.0...U....VozIP1.0...U....Irontec1 0...*.H........vozip@irontec.com...........0...U....0....0...*.H............T.-F....R..2%.....T......=9.ye.z..6.0............i...O;.../s..e.........S.6.31......!iT......N....]........>XNt....Z...MHKH3...K.........

**SRTP**
-Para configurar SRTP tenemos que poner la directiva ‘encryption’ en los peers (ya sean realtime o en sip.conf)

encryption=yes

-En los SPA5XX hay que tocar 3 valores. Esto es configurable al menos, desde la versión 7.4.3 del firmware (OJO! que se aplica para todas las líneas configuradas):
+SRTP Method: s-descriptor

+Secure Call Serv: yes

+Secure Call Setting: yes

Voilá! Ya tenemos SRTP configurado!
DETALLE: No hay modo opcional de SRTP para Asterisk, es decir, si está encryption activado en el peer no aceptará audio no cifrado y al contrario. En los terminales en cambio, si está el cifrado configurado, pero no el peer como tal, las llamadas entrantes se establecerán sin problemas. No así, las salientes, porque el terminal hemos dicho que tenía SRTP activo y para Asterisk no. En los Snom se puede utilizar también el modo ‘Optional’ para el SRTP (envía dos atributos m=audio con y sin SRTP), pero Asterisk no sabe manejar estos SDP… :S

4. Pruebas
Para probar todo esto lo más fácil es capturar tráfico en la red y después verificar con WireShark, OmniPeek o cualquier otro software si vemos la señalización en claro y si podemos escuchar las conversaciones.
En los test realizados en nuestro lab, nos encontramos con un Warning (no siempre) en el CLI, pero en principio todo funciona como debe.

WARNING[25205]: res_srtp.c:338 ast_srtp_unprotect: SRTP unprotect: authentication failure

Estamos debuggeando este último punto para ver que puede estar provocándolo…

**Curiosidad**
Los CiscoSPA5XX cuando están con SRTP activado, reproducen una especie de “beep” tres veces al principio de la conversación y muestran en pantalla un $ como símbolo de conversación encriptada. Un ejemplo:

Al final ha quedado un post un tanto largo… pero bueno, esperemos que sirva a alguien! ;P
Como siempre, cualquier duda/consulta/crítica será bienvenida.

Un saludo!

Te ha gustado? Compartelo:
  • Print
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • BarraPunto
  • Meneame
  • Twitter

Nuevas funcionalidades de Asterisk 1.8: Update de CallerID

La versión 1.8 de Asterisk ha aportado nuevas features interesantes, como por ejemplo, CEL, SRTP, soporte para fax, calendarios compartidos, soporte IPv6…

En este caso nos vamos a centrar en una feature simple pero que los clientes que provienen de centralitas comerciales suelen echar en falta. La actualización del CLID en transferencias. Hablamos en todo momento de transferencias atendidas y realizadas mediante REFER-s, es decir, transferencias a través del propio terminal y no a través de las features nativas de Asterisk.
Para que funcione, hay que configurar un par de cosas en sip.conf:

  • Si queremos utilizar la cabecera SIP Remote-Party-ID:
    sendrpid=yes o sendrpid=rpid (es lo mismo)
  • Si queremos utilizar la cabecera SIP P-Asserted-Identity:
    sendrpid=pai
  • Obligatoriamente:
    directmedia=update

Es necesario configurar directmedia a update (además del sendrpid) para que Asterisk envíe mensajes SIP de tipo UPDATE ya que si envía INVITE-s (re-invites para decir que el audio está en otro punto) recibimos un mensaje 500 (Internal Server Error) por parte del terminal de destino final. Es decir, cuando se hace el REFER Asterisk le envía un INVITE al destino final diciendo que el audio lo tiene él, para acto seguido enviarle otro INVITE (CSeq+1) diciendo que el audio está en otro terminal (PtP audio). A este segundo INVITE es al que el terminal responde con un 500.
Espero que en la siguiente imagen se entienda mejor:

Ahora la captura SIP completa con “directmedia=yes” & “sendrpid=yes” donde:

    Asterisk => 10.10.0.165
    C phone (300) => 10.10.0.142
    B phone (200) => 10.10.0.177
    A phone (100) => 10.10.0.167

Esta vez, la captura SIP completa con Ngrep y “directmedia=update” & “sendrpid=yes/pai” donde:

    Asterisk => 10.10.0.165
    C phone (300) => 10.10.0.142
    B phone (200) => 10.10.0.177
    A phone (100) => 10.10.0.167

No me es posible presentar la captura con una imagen como la superior (el software omnipeek no “ve” los UPDATE-s), así que os dejo unas trazas en los siguientes enlaces:
Traza SIP con sendrpid=yes
Traza SIP con sendrpid=pai

Después de tanta traza SIP, comentar también que no sirve cualquier terminal (o mejor dicho cualquier firmware¿?), tiene que aceptar UPDATEs. Con los Cisco SPA5xx funciona a la perfección. Los Linksys SPA9xx no aceptan Updates y algunos Snom y Aastra tampoco… aunque tampoco me he puesto a jugar demasiado con la configuración de estos últimos.

Como se ha comentado en la entradilla del post, aquí se habla en todo momento de transferencias atendidas. En el caso de transferencias semi-atendidas (xfer->dial->xfer sin haber establecido la segunda llamada) funciona a la perfección en cualquier caso. Me explico, utilicemos audio PtP o no, bien con UPDATEs, bien con INVITEs, Asterisk envía un UPDATE para actualizar los datos de sesión cuando la segunda llamada no ha sido establecida, por lo que el CLID se actualiza sin problemas. Las transferencias ciegas también funcionan correctamente (en la versión 1.8.0 había un Bug que se solucionó más tarde).

Espero haberme explicado bien. Estamos aquí para cualquier duda/sugerencia o corrección.

Un saludo.

Te ha gustado? Compartelo:
  • Print
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • BarraPunto
  • Meneame
  • Twitter

Log en Asterisk

A menudo cuando una centralita tiene alta carga, ver la consola o los logs que genera Asterisk en /var/log/asterisk/messages no es suficiente. Porque se genera gran cantidad de información, porque al tener muchas llamadas concurrentes seguir una llamada en concreto a través de saltos en un fichero es complicado, porque a medida que integramos más y más herramientas con Asterisk las llamadas ya no se controlan o se localizan en un único punto…

Lo que vamos a intentar es tener controlado el log de todo el sistema, incluyendo Asterisk, su dialplan, los agis y cualesquira herramientas que usemos. Los objetivos son claros:

  • Tener todos los logs relevantes en un lugar unificado de tal forma que podamos seguir la pista a las llamadas o a los errores sin tener que hacer merges mentales de múltiples fuentes.
  • Tener los logs marcados y clasificados de tal forma que podamos encontrar de forma cómoda y sencilla cualquier información puntual que necesitemos.
  • Loguear todo lo que ocurre en la plataforma remotamente relacionado con el flujo de las llamadas y el correcto funcionamiento de las mismas.

En este post vamos a ver un ejemplo de cómo hacer esto con un criterio arbitrario. Se pretende que cualquira pueda adaptar este ejemplo a sus necesidades. En este ejemplo vamos a querer:

  1. Los logs generales del sistema para ver que todo es correcto. Esto es, el syslog. Deberemos filtrar cúales de los servicios del sistema que loguean al syslog queremos ver y cuáles no.
  2. Los logs relacionados con el flujo de una llamada. En este caso vamos a suponer que dialplan y agis.

Todo esto lo vamos a hacer a través del syslog del sistema y las opciones que nos brinda para filtrar y etiquetar los logs.  ¡Manos a la obra!

(más…)

Te ha gustado? Compartelo:
  • Print
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • BarraPunto
  • Meneame
  • Twitter

Provisionamiento Linksys SPA9XX

Hace poco he necesitado hacer un poco de mass-deployment de teléfonos Linksys SPA922. La verdad es que son terminales que me gustan mucho. He probado los Thompson,los Grandstream y Snom de gama baja/media y la verdad es que para terminales comunes, no de operadora, me quedo con los Linksys: son bonitos y fiables.

El problema me llega cuando busco en Google ficheros de ejemplo sobre el provisionamiento de Linksys. No encuentro ningún ejemplo y tampoco explicaciones claras sobre cómo hacerlo. Bien, esto me pasa por no leerme completito el manual de administrador de los terminales donde en un párrafo se explica bien claro. El motivo de este post es que otro no pierda el tiempo que he perdido yo buscando en google algo tan sencillo.

Un fichero de provisionamiento de Linksys SPA9XX no es más que un fichero XML y es bastante sencillo de hacer. Voy a poner el ejemplo de un SPA922 pero es bastante generalizable a toda la gama.

Lo primero es saber que toda la configuración va en un fichero al que llamaremos spa922.cfg. El fichero admite todas las opciones que vemos normalmente en el interfaz web del terminal sin más que respetar algunas convenciones:

  • Los espacios en las opciones se sustituyen por guiones bajos
  • Las opciones asociadas a una línea han de llevar _X_ al final del nombre de la opción. X hace referncia al número de línea.
  • El fichero empieza y termina con las etiquetas <flat-profile></flat-profile>.

Pongo aquí un ejemplo de fichero. En realidad de dos porque las opciones comunes a todos los teléfonos se ponen en un único fichero y después las opciones particulares, tales como los datos de acceso, se ponen en ficheros individuales para cada teléfono. El genérico es el antes mencionado “spa922.cfg” y el particular es “spa922-${MAC}.cfg”

  1.  
  2. <flat-profile>
  3.  
  4.   <!– PROVISIONING –>
  5.   <resync_periodic>10</resync_periodic>
  6.   <resync_error_retry_delay>20</resync_error_retry_delay>
  7. <profile_rule>/spa922-MAC/spa922-$MA.cfg</profile_rule>
  8.  
  9.   <!– SYSTEM –>
  10.   <enable_web_server>yes</enable_web_server>
  11.   <enable_web_admin_access>yes</enable_web_admin_access>
  12.   <dhcp>yes</dhcp>
  13. <primary_ntp_server>10.10.10.1</primary_ntp_server>
  14.   <enable_vlan>no</enable_vlan>
  15.   <enable_cdp>no</enable_cdp>
  16.  
  17.   <!– SIP –>
  18.   <max_forward>70</max_forward>
  19.   <max_redirection>5</max_redirection>
  20.   <max_auth>2</max_auth>
  21.   <sip_user_agent_name>$VERSION</sip_user_agent_name>
  22.   <sip_reg_user_agent_name>$VERSION</sip_reg_user_agent_name>
  23. <dtmf_relay_mime_type>application/dtmf-relay</dtmf_relay_mime_type>
  24.   <use_compact_header>no</use_compact_header>
  25.   <rtp_port_min>8000</rtp_port_min>
  26.   <rtp_port_max>11000</rtp_port_max>
  27.   <symmetric_rtp>yes</symmetric_rtp>
  28.   <stun_enable>no</stun_enable>
  29.  
  30.   <!– REGIONAL –>
  31.   <time_zone>GMT+01:00</time_zone>
  32.  
  33.   <!– PHONE –>
  34.   <voice_mail_number>451</voice_mail_number>
  35.   <text_logo>Irontec%0ai::voz</text_logo>
  36.   <extension_1_>1</extension_1_>
  37.   <share_call_appearance_1_>private</share_call_appearance_1_>
  38.  
  39.   <!– EXT 1 –>
  40. <line_enable_1_>yes</line_enable_1_>
  41.   <subscription_expires_1_>3600</subscription_expires_1_>
  42.   <sip_port_1_>5060</sip_port_1_>
  43. <proxy_1_>10.10.10.1</proxy_1_>
  44.   <use_outbound_proxy_1_>no</use_outbound_proxy_1_>
  45.   <register_1_>yes</register_1_>
  46.   <make_call_without_reg_1_>no</make_call_without_reg_1_>
  47.   <register_expires_1_>3600</register_expires_1_>
  48.   <use_dns_srv_1_>no</use_dns_srv_1_>
  49.   <use_auth_id_1_>No</use_auth_id_1_>
  50. <preferred_codec_1_>G711a</preferred_codec_1_>
  51.   <use_pref_codec_only_1_>no</use_pref_codec_only_1_>
  52.   <g729a_enable_1_>yes</g729a_enable_1_>
  53.   <g723_enable_1_>no</g723_enable_1_>
  54.   <g726-16_enable_1_>no</g726-16_enable_1_>
  55.   <g726-24_enable_1_>no</g726-24_enable_1_>
  56.   <g726-32_enable_1_>no</g726-32_enable_1_>
  57.   <g726-40_enable_1_>no</g726-40_enable_1_>
  58. <dtmf_tx_method_1_>auto</dtmf_tx_method_1_>
  59.   <dial_plan_1_ ua="na">(1xxS0|2xxS0|6xxxxxxxxS0|9xxxxxxxxS0|xx.)</dial_plan_1_>
  60.   <enable_ip_dialing_1_ ua="na">No</enable_ip_dialing_1_>
  61.  
  62.   <!– User –>
  63.   <time_format>24hr</time_format>
  64.  
  65. </flat-profile>
  1. <flat-profile>
  2.  
  3.   <display_name_1_>Jon Bonilla</display_name_1_>
  4.   <user_id_1_>205</user_id_1_>
  5. <password_1_>secretillo</password_1_>
  6.  
  7. </flat-profile>

Una vez tenemos los dos ficheros, sólo necesitamos que el terminal sepa dónde encontrarlos. Hay varias maneras de hacerlo; la que he escogido es tener un servidor tftp en mi asterisk que sirva los ficheros al teléfono. Para ellos debemos instalar un servidor tftp. Para ellos como root instalamos atftp:
apt-get install atftpd
Editamos /etc/default/atftpd para decirle dónde estará nuestro directorio de tftp. En mi caso /tftpboot:
USE_INETD=true
OPTIONS="--daemon --port 69 --tftpd-timeout 300 --retry-timeout 5 --mcast-port 1758 --mcast-addr 239.239.239.0-255 --mcast-ttl 1 --maxthread 100 --verbose=5 /tftpboot"

Creamos el directorio /tftpboot y ponemos ahí el fichero general spa922.cfg. Después creamos el directorio “/tftpboot/spa922-MAC” donde irán los ficheros particulares de cada teléfono. Por ejemplo el “spa922-000e08de2995.cfg”

Ahora ya tenemos todo preparado. Sólo queda hacer saber al terminal dónde ha de buscar el servidor tftp. Para ello, lo que hacemos es pasarle una option desde el servidor dhcp cuando el terminal hace una petición. En el fichero de configuración del servidor dhcp /etc/dhcp3/dhcpd.conf tendríamos algo así:


subnet 10.10.10.0 netmask 255.255.255.0
{
range 10.10.10.100 10.10.10.254;
option domain-name-servers 212.55.8.132;
option routers 10.10.10.1;
option subnet-mask 255.255.255.0;
option broadcast-address 10.10.10.255;
option tftp-server-name "10.10.10.1";
}

Después de esto, tenemos que cuando enchufemos a la red el terminal nuevo éste cogerá la dirección de red del servidor, comprobará que hay un servidor tftp en el que encontrará sus ficheros de configuración y tendremos el terminal listo para usar sin haber tenido que tocar para nada el terminal o haber accedido a la configuración web. Esto es una gran ventaja en cuanto el número de terminales a implantar es mayor de unos pocos. Además si por alguna razón tenemos un usuario torpe y mete la pata, basta con reinicar el teléfono y éste se volvería a configurar con los valores correctos.

Para más parámetros a configurar en los terminales lo mejor es verlos todos detallados en el manual de linksys.

Te ha gustado? Compartelo:
  • Print
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • BarraPunto
  • Meneame
  • Twitter

Google Calendar en Asterisk

Hace no mucho comentábamos el uso de un calendario en webdav para que Asterisk comprobara los días festivos al recibir una llamada y supiera si debía permitir la llamada o saltar directamente al buzón de voz.

En esta entrada vamos a hacer algo parecido pero esta vez usando Google Calendar, el cual nos permite acceder a los eventos mediante una URL que apunta a nuestro calendario en formato Icalendar. Haremos que nuestro Asterisk consulte nuestro Google Calendar para tratar las llamadas entrantes y sepa si debe pasar la llamada, desviarla o saltar al buzón de voz del usuario.

Lo primero que haremos será crear una cuenta en google si no tenemos una. Con esta cuenta podemos crear tantos calendarios como queramos. En este caso crearemos un calendario para marcar los festivos de la empresa. Vamos a obviar los pasos a seguir para crear un calendario y supongamos que ya tenemos un calendario creado para tal efecto.

A la izquierda de la panatalla veremos nuestros calendario entre todos los que tenemos asociados a nuestra cuenta y debajo de ellos un enlace administrar calendarios.

Lista de calendarios

Pinchamos en administrar calendario y en la pantalla que nos sale elegimos el calendario que hayamos creado para marcar los festivos. Ahora tenemos una pantalla en la que podemos editar las propiedades del calendario, compartirlo con otros usuarios…etc. En este caso lo que nos interesa es la sección llamada Dirección Privada.

Dirección Privada

Vemos tres iconos XML ICAL HTML que nos dan acceso a nuestro calendario en diferentes formatos. En este caso lo que nos interesa es el formato ICAL. Guardamos la dirección del enlace al que apunta el icono porque es lo que vamos a usar para leer el calendario.

Una vez creado el calendario solo nos queda marcarlo con diferentes festivos. Podemos simplemente poner Festivo o podemos discriminar más y diferenciar todo lo que queramos. En este howto vamos a diferenciar festivos locales, festivos nacionales y festivos de empresa. Lo que vamos a hacer es crear un evento el día en cuestión, a cualquier hora y de cualquier duración, en el que pongamos estas etiquetas:

festivos

Una vez tenemos el calendario llega el momento de usarlo. Vamos a crear un AGI en ruby que consulte nuestro calendario y devuelva a asterisk una variable SALTO que usaremos en el dialplan.

calendario.rb

  1. #!/usr/bin/ruby
  2. require ‘rubygems’
  3. require ‘icalendar’
  4. require ‘open-uri’
  5. include Icalendar
  6. URL="http://www.google.com/calendar/ical/xxxxxx%40irontec.com/private-XXXXXXXXXXXXXXXXXX/basic.ics"
  7. calendarios = Icalendar.parse(open(URL))
  8. calendario = calendarios[0]
  9. festivo=nil
  10. calendario.events.each do |evento|
  11. if evento.dtstart.yday == Date.today.yday
  12. festivo=evento.summary
  13. break
  14. end
  15. end
  16. #Festivos
  17. if festivo == nil
  18. salto = "laboral"
  19. elsif festivo == "Festivo Irontec"
  20. salto = "festivo-irontec"
  21. elsif festivo == "Festivo Nacional"
  22. salto = "festivo-nacional"
  23. elsif festivo == "Festivo Local"
  24. salto = "festivo-local"
  25. else
  26. salto = "laboral"
  27. end
  28. print("SET VARIABLE SALTO #{salto}")
  29. exit

Una vez hecho esto ya solo tenemos que hacer el tratamiento en el dialplan. Doy por supuesto que ya sabemos hacer esto así que voy a poner una líneas meramente descriptivas:

  1. [entrantes]
  2. exten => 944048182,1,AGI(calendario.rb)
  3. exten =>944048182,n,Goto(${SALTO},s,1)
  4. [laboral]
  5. exten =>  s,1,NoOp(Aqui tratamiento de día laboral)
  6. [festivo-nacional]
  7. exten => s,1,NoOp(Festivo nacional)

Una vez hecho esto ya solo nos queda probarlo para ver que todo esta correcto. Ya tenemos una centralita aún más inteligente que demuestra una vez más que Asterisk está a años luz de las centralitas tradicionales. ¡Bienvenidos a la telefonía del siglo XXI!

Nota -> Siento lo de la indentación y coloreado del código pero wordpress es un mal bicho. Voy a ver si le hago la pelota a uno de mis compañeros del departamento web para que me hackeen un poco el CSS :)

Te ha gustado? Compartelo:
  • Print
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • BarraPunto
  • Meneame
  • Twitter

Parche para APP_Rxfax : Consultar estado

SpanDSP es una librería para el Procesamiento Digital de Señales (DSP) que necesitaremos para poder transmitir/recibir Fax a través de asterisk. Junto con SpanDSP los autores facilitan dos aplicaciones para enviar fax y recibir fax en asterisk (rx_fax y tx_fax). A pesar de que puedes encontrar buenos manuales para hacerlas funcionar no siempre consigues los resultados esperados.

Y es que si consultamos la ayuda de txFax:

----------------------------------------
TxFAX(filename[|caller][|debug]): Send a given TIFF file to the channel as a FAX.
The "caller" option makes the application behave as a calling machine,
rather than the answering machine. The default behaviour is to behave as
an answering machine.
Uses LOCALSTATIONID to identify itself to the remote end.
LOCALHEADERINFO to generate a header line on each page.
Sets REMOTESTATIONID to the receiver CSID.
Returns -1 when the user hangs up, or if the file does not exist.
Returns 0 otherwise.
----------------------------------------
El retorno (0 y -1) es una practica común en el desarrollo de aplicaciones para c, pero no así en asterisk, donde es mas común devolver algún valor en una variable o saltar a una prioridad +101.

Por lo que se hace muy difícil consultar el estado del envío, si se ha enviado con éxito o no, ya que la manera de actuar de esta aplicación es la siguiente:

  • Si el fax llega bien entonces se continúa con el dialplan, pero no hay NINGUNA variable para advertir ese resultado.
  • Si el fax llega mal entonces se pasa directamente a la extensión Hangup del contexto, igualmente sin dejar un resultado en una variable.

Aplicando la siguiente linea a la aplicación se consigue modificar el comportamiento de esta:


static void phase_e_handler(t30_state_t *s, void *user_data, int result)
{
struct ast_channel *chan;
char far_ident[21]; chan = (struct ast_channel *) user_data;
if (result == T30_ERR_OK)
{
t30_get_far_ident(s, far_ident);
pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", far_ident); /******************* LINEA PARA MODIFICAR ******************************/
pbx_builtin_setvar_helper(chan, "RESULTADO", "ENVIADO"); }
else
{
ast_log(LOG_DEBUG, "==============================================================================n");
ast_log(LOG_DEBUG, "Fax send not successful - result (%d) %s.n",result,t30_completion_code_to_str(result));
ast_log(LOG_DEBUG, "==============================================================================n"); /******************* LINEA PARA MODIFICAR ******************************/
pbx_builtin_setvar_helper(chan, "RESULTADO", "ERROR");
}
}
/*- End of function --------------------------------------------------------*/

Gracias a esa función se puede dar un valor a una variable de canal, y como ocurre cuando el resultado es correcto se continúa con el dialplan.

Aqui dejamos el parche para que app_txfax devuelva una variable de estado. Su uso es muy facil:

# cd /usr/src/asterisk/apps

# patch app_txfax.c < app_txfax.patch
Te ha gustado? Compartelo:
  • Print
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • BarraPunto
  • Meneame
  • Twitter

Dialplan para grabación de voces vía llamada telefónica

Introducción

En ocasiones puede ser suficiente el grabar las voces del menú menú IVR de nuestro Asterisk a través de una llamada telefónica. Esta opción se hace aún más interesante cuando el locutor no está con nosotros o cuando sencillamente no desponemos de equipamiento más profesional para grabación de voces.

A continuación se muestra un dialplan para Asterisk que constituye un cómodo y sencillo menú de grabación de voces.

Funcionamiento

La mecánica del dialplan es sencilla, todo se puede realizar con una única llamada. Tras la grabación de cada voz podremos escucharla y regrabarla, o bien elegir otra voz:

Esquema:

  • El usuario llama y se le introduce en el contexto grabacion_voces.
  • Se le solicita introduzca una contraseña para autenticarle.
  • Se le pide que marque un número (de n cifras) que se corresponde con una determinada voz a grabar (XX).
  • Se le manda al contexto grabacion_voces_opciones donde primeramente escucha la grabación actual del sonido.
  • Se le presenta un menú con las opciones:
    • 0 -> Grabar su voz para este sonido.
    • 1 -> Escuchar su grabación.
    • 2 -> Ir a otros sonidos.

De esta forma, mediante una única llamada podemos gestionar todas las voces, o las que nos interesen en cada ocasion.

(más…)

Te ha gustado? Compartelo:
  • Print
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • BarraPunto
  • Meneame
  • Twitter

Integración de softphone y agenda de contactos

integration.jpg

En ocasiones puede ser interesante el uso de softphones en lugar de teléfonos de sobremesa, por ejemplo cuando se requiere manejar un ordenador mientras mantenemos una conversación telefónica.

Dentro de este escenario, en el que la telefonía radica en un programa de software, sería interesante ganar en agilidad aprovechando la integración de nuestro softphone con nuestra aplicación de agenda de contactos.

Objetivo

Buscar soluciones para realizar llamadas telefónicas desde nuestra agenda de contactos, sin la necesidad de tener que marcar el número de teléfono manualmente en el softphone.

Algunos softphones incluyen una pequeña agenda de contactos, pero sólo tienen validez para el propio softphone. Entendemos en este artículo que el usuario prefiere tener su agenda centralizada en una aplicación independiente y más completa (correo, agenda, notas, tareas, calendario, etc).

Por cuestiones ideológicas haremos hincapié sólo en soluciones de software libre, entendiendo que son además las que mejor permiten ser adaptadas a nuestras necesidades y las que mayor flexibilidad ofrecen.

(más…)

Te ha gustado? Compartelo:
  • Print
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • BarraPunto
  • Meneame
  • Twitter

Consulta los festivos de un calendario WebDAV desde Asterisk

Calendario Festivos

Introducción

Una de las grandes ventajas de las centralitas basadas en Asterisk es su flexibilidad a la hora de realizar implantaciones. Asterisk Gateway Interface (AGI) dota a nuestra centralita de una potencia sin igual para la integración de la misma con diferentes servicios dentro de la empresa, como CRM, ERP o un calendario compartido como es el caso del presente tutorial.

A lo largo de este “howto” aprenderemos a implementar un sistema de consultas de calendario mediante un AGI de Asterisk.

Objetivo

Nuestra empresa quiere que la centralita responda con un mensaje de bienvenida específico los festivos y fines de semana.

La información sobre las fechas en las que la empresa cierra al público estará contenida en un calendario editable desde los clientes PIM.

Resumen

  • Instalaremos un servidor Apache2 + WebDav para compartir un calendario en formato ICalendar, todo ello en el servidor Debian Sarge que alberga nuestra centralita Asterisk.
  • Configuraremos el calendario en nuestro cliente PIM para consultarlo y editarlo.
  • Crearemos un AGI que consulte el día actual en el calendario y responda con un mensaje de aviso en caso de que sea festivo o fin de semana.

(más…)

Te ha gustado? Compartelo:
  • Print
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • BarraPunto
  • Meneame
  • Twitter