jueves 30 de agosto de 2007

Asterisk: Parche chan_sip para permitir espiral SIP

El "chan_sip" versión 1 presente en Asterisk adolece de la posibilidad de recibir de vuelta un INVITE con el URI modificado. Este hecho se hace palpable cuando usamos un proxy SIP en conjunción con Asterisk.

El problema

Supongamos que tenemos nuestros usuarios SIP en OpenSer y que tenemos un Asterisk para ofrecer servicios de media así como pasarela a la PSTN. Imaginemos el siguiente caso (bastante deseable entiendo yo):

  • Asterisk recibe una llamada vía PSTN y la pone en contacto con un usuario SIP de OpenSer haciendo Dial(SIP/200@openser.mydomain.org).
  • El INVITE llega a OpenSer, quien consulta sus tablas de lógica y encuentra un "forwarding" del usuario "sip:200" al número "675123123".
  • Entonces OpenSer reescribe la URI del INVITE dejándola así: sip:675123123@asterisk.mydomain.org.
  • Así pues dicho INVITE llega de vuelta al Asterisk para que éste efectúe una llamada de móvil.
  • Problema: Cuando Asterisk recibe este INVITE de vuelta reconoce que se trata del INVITE que él envió y lo rechaza con "482 Loop Detected".

En fin, una faena que impide una característica tan vistosa y útil. :(

La solución

Por suerte hay más gente consciente de este problema y con capacidad de modificar el código de Asterisk. En concreto, para solucionar el problema existe un parche gestado a partir de un reporte en el tracker de Asterisk:

0007403: [patch] allow SIP Spiral to work instead of causing a '482 Loop Detected' condition

Por desgracia dicho parche está disponible sólo para la versión Asterisk 1.4 SVN 48358 (ahora van por la 81388). Pero no costaría mucho adaptarlo a la versión trunk.

A testearlo pues

Una vez que unos pocos hemos testeado el funcionamiento del parche lo que toca es que más gente lo haga para que los desarrolladores tengan bien claro que funciona y lo integren cuanto antes en la rama oficial. Así pues indico ahora paso a paso como testearlo:

Descargar la versión SVN 48358 de Asterisk:

~# cd /usr/src
~# svn checkout http://svn.digium.com/svn/asterisk/trunk asterisk-svn48358 -r 48358

Descargar el parche del tracker de Asterisk. Abrir ésta URL y descargar el fichero "sip_spiral.patch" disponible en la sección "Attached Files".

Aplicar el parche modificado:

~# mv sip_spiral3.patch /usr/src/asterisk-svn48358
~# cd /usr/src/asterisk-svn48358
~# patch -p0 < sip_spiral3.patch

Si no hay problemas (no debería) sólo queda compilar e instalar Asterisk como siempre:

~# ./configure
~# make menuselect => En "4. Codec Translators" desactivar "codec_zap" (al menos a mí me falla en esta versión)
~# make
~# make install

Nota: Antes del "make install" es recomendable borrar todos los módulos en "/usr/lib/asterisk/modules".

Reiniciamos Asterisk y en principio ya estaría. Ahora sólo falta montar el escenario de prueba:

  • En OpenSer ponemos un alias de "sip:200@openser.mydomain.org" a "sip:675123123@asterisk.mydomain.org".
  • Ponemos Asterisk permitiendo llamadas anónimas desde cualquier sitio (por no complicarnos la vida).
  • Definimos una extensión exten => test,1,Dial(SIP/200@openser.mydomain.org).
  • Definimos una extensión exten => _6XXXXXXXX,1,PlayBack(demo-congrats) (o si podemos que llame vía PSTN o proveedor SIP).

Y lo probamos:

  • Desde un tfno SIP llamamos a "sip:test@asterisk.mydomain.org".
  • La llamada llega a Asterisk quien generará un INVITE a "sip:200@openser.mydomain.org".
  • Ese INVITE llegará a OpenSer quien comprobará el alias y reescribirá la URI enviando de vuelta a Asterisk a la URI "sip:675123123@asterisk.mydomain.org".
  • Asterisk recibirá el mismo INVITE que él generó pero con URI modificada. Ahora gracias al parche no rechazará la llamada y mostrará:
    --- set_address_from_contact host 'XX.XX.XX.XX' -- Playing 'demo-congrats' (language 'en') -- SIP/openser-081c2c18 answered SIP/openser-081c4d18 -- Packet2Packet bridging SIP/openser-081c4d18 and SIP/openser-081c2c18
  • Además tocaría comprobar que todas las respuestas desde Asterisk pasan por OpenSer (se supone que hemos añadido "Record-Route" y tal).

Confirmar si funciona

En caso de que funcione os pido que me lo confirméis o bien lo hagais saber directamente en el tracker de Asterisk para que los desarrolladores tengan cierta garantía y puedan subir el parche al trunk. ;)