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

0 Comments.