Asterisk 11.X - Mensajes instantáneos SIP <-> XMPP

La idea de este articulo es demostrar que con Asterisk 11.X es posibles enviar mensajes instantáneos desde una extensión SIP a un usuario XMPP (Jabber) y viceversa. El escenario tiene algunas limitaciones pero creo que puede ser una solución si quieren mantener el flujo de mensajes en servidores seguros y directamente gestionados por ustedes.

Para esta prueba se ha utilizado:

  • Un Raspberry
  • Asterisk 11.7
  • Un servidor Openfire instalado en un segundo servidor
  • Un Softphone X-Lite
  • El cliente Spark

La idea es que cada extensión tenga un usuario XMPP configurado y que ese usuario se añada a la base de datos interna de Asterisk asociándolo con su numero de extensión. En este caso el usuario XMPP será raspberry y será asociado a la extensión 209. El segundo usuario XMPP será voztovoice.

Para empezar se crean los dos usuario en el servidor Openfire.

Captura

Luego se configura el usuario Raspberry en Asterisk.

Se modifica el archivo xmpp.conf para que quede:

[general]
debug=no
autoprune=yes
autoregister=yes
;collection_nodes=yes
;pubsub_autocreate=yes
auth_policy=accept

[raspberry]
type=client
serverhost=voztovoice.net
;pubsub_node=pubsub.voztovoice.net
username=raspberry@voztovoice.net/asterisk
secret=password
priority=1
port=5222
usetls=yes
usesasl=yes
buddy=voztovoice@voztovoice.net
;distribute_events=yes
status=available
statusmessage="Extensión 209"
timeout=5
sendtodialplan=yes
context=messages209

Los datos importantes:

  • buddy=voztovoice@voztovoice.net – Se añade el usuario voztovoice a la lista de contactos
  • statusmessage="Extensión 209" – Para que los usuarios XMPP sepan que el usuario raspberry está asociado a la extensión 209
  • sendtodialplan=yes – Los mensajes instantáneos enviados al usuario raspberry se enviarán al dialplan
  • context=messages209 – al contexto messages209 que hay que crear

Si se quiere asociar otro usuario a otra extensión, nada más crear otro bloque parecido al de [raspberry]. En el caso que se quiera asociar el usuario fulano a la extensión 210, sería:

[fulano]
type=client
serverhost=voztovoice.net
;pubsub_node=pubsub.voztovoice.net
username=fulano@voztovoice.net/asterisk
secret=password
priority=1
port=5222
usetls=yes
usesasl=yes
buddy=voztovoice@voztovoice.net
;distribute_events=yes
status=available
statusmessage="Extensión 210"
timeout=5
sendtodialplan=yes
context=messages210

Luego en la base de datos interna de Asterisk se asocia el usuario fulano a la extensión 210. Para esta prueba se crea solamente uno. Se guardan los cambios y se recarga el modulo res_xmpp.so:

asterisk -rvvvvvvvvvvvvvvv

CLI> module reload res_xmpp.so

se mira si el usuario está conectado:

CLI> xmpp show connections

Jabber Users and their status:
       [raspberry] raspberry@voztovoice.net/asterisk     - Connected

y que pasa con los contactos:

CLI> xmpp show  buddies

Buddy:  voztovoice@voztovoice.net

Se asocia el usuario raspberry a la extensión 209 en la base de datos interna de Asterisk:

asterisk -rvvvvvvvvvvvv

CLI> database put ext 209 raspberry

El usuario voztovoice todavía no está conectado. Se abre el cliente Spark y se configura el usuario voztovoice:

Captura

Se presiona el enlace Login y se espera que el cliente se conecte al servidor Openfire. El resultado será:

Captura

En la consola de Asterisk:

CLI> xmpp show buddies

Buddy:  voztovoice@voztovoice.net
                Resource: Spark 2.6.3
                        node:
                        version:
                        Google Talk capable: no
                        Jingle capable: no

En la pagina de administración de Openfire:

Captura

De los mensajes instantáneos entre extensiones SIP se ha hablado en este articulo; lo importante es que la parte general del sip.conf contenga estos parámetros:

accept_outofcall_message = yes
outofcall_message_context = messages
auth_message_requests = yes

Ahora se pasa al dialplan:

nano /etc/asterisk/extensions.conf

en el contexto configurado en la parte general del sip.conf para los mensajes instantáneos, se añade el siguiente bloque:

[messages]
exten => s,1,Noop(Mensaje de ${MESSAGE(from)})
same => n,Noop(Mensaje para ${MESSAGE(to)})
same => n,Noop(Texto = ${MESSAGE(body)})
same => n,Messagesend(sip:${EXTEN},${MESSAGE(from)})
same => n,Noop(Estado del mensaje ${MESSAGE_SEND_STATUS})
same => n,Hangup

Esto para los mensajes entre extensiones SIP. Luego para los mensajes recibidos por el usuario raspberry que se envian hacia la extensión 209:

[messages209]
exten => s,1,Noop(Mensaje de ${MESSAGE(from)})
same => n,Noop(Mensaje para ${MESSAGE(to)})
same => n,Noop(Texto = ${MESSAGE(body)})
same => n,Messagesend(sip:209,${MESSAGE(from)})
;same => n,Noop(Estado del mensaje ${MESSAGE_SEND_STATUS})
same => n,Hangup

Si se creara el usuario fulano, extensión 210, habría que añadir otro bloque de este tipo:

[messages210]
exten => s,1,Noop(Mensaje de ${MESSAGE(from)})
same => n,Noop(Mensaje para ${MESSAGE(to)})
same => n,Noop(Texto = ${MESSAGE(body)})
same => n,Messagesend(sip:210,${MESSAGE(from)})
;same => n,Noop(Estado del mensaje ${MESSAGE_SEND_STATUS})
same => n,Hangup

Se guardan los cambios y se actualiza el dialplan:

asterisk -rvvvvvvvvvvvv

CLI> dialplan reload

Desde el usuario configurado en Spark se envía un mensaje al usuario raspberry:

Captura

En X-Lite:

Captura

Si se intenta devolver el mensaje desde el X-Lite no pasará absolutamente nada. Se activa el debug en la consola de Asterisk:

CLI> sip set debug on

y se intenta enviar un segundo mensaje al usuario raspberry:

--- (12 headers 1 lines) ---
Receiving message!
Found peer '209' for '209' from 79.44.192.186:6000
Looking for asterisk in messages (domain 190.66.155.15)

<--- Transmitting (NAT) to 79.44.192.186:6000 --->
SIP/2.0 404 Not Found
Via: SIP/2.0/UDP 192.168.1.101:6000;branch=z9hG4bK-d8754z-e77ccb0a9afa464b-1---d8754z-;received=79.44.192.186;rport=6000
From: "209"<sip:209@voztovoice.noip.us:2464>;tag=2cf27935
To: "xmpp:voztovoice@voztovoice.net/Spark 2.6.3"<sip:asterisk@190.66.155.15:2464>;tag=as502bc767
Call-ID: OGVjNzAzM2FlODUzNzdiN2M5OWRiYjAyODU1M2JlOGU
CSeq: 7 MESSAGE
Server: Raspberry pi PBX
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH
Supported: replaces, timer
Content-Length: 0

Como se puede ver Asterisk intenta enviar el mensaje al contexto [messages] extensión asterisk. Si se fijan en el segundo bloque, campo To: aparece el usuario XMPP voztovoice@voztovoice.net. Utilizando estas dos informaciones se modifica nuevamente el dialplan y en el contexto [messages] se añade un segundo bloque:

exten => asterisk,1,Noop(Mensaje hacia usuarios XMPP)
same => n,NoOp(${MESSAGE(from)})
same => n,Set(from=${CUT(MESSAGE(from),:,2)})
same => n,Set(from=${CUT(from,@,1)})
same => n,Set(from=${DB(ext/${from})})
same => n,NoOp(${MESSAGE_DATA(to)})
same => n,Set(to=${MESSAGE_DATA(to)})
same => n,Set(to=${CUT(to,:,2)})
same => n,Set(to=${CUT(to,/,1)})
same => n,Noop(Texto = ${MESSAGE(body)})
same => n,JabberSend(${from},${to},${MESSAGE(body)})
same => n,Noop(Estado del mensaje ${MESSAGE_SEND_STATUS})
same => n,Hangup

Primero desde la variable ${MESSAGE(from)} se extrae con la función CUT el numero de la extensión que está enviando el mensaje. Luego se lee en la base de datos interna de Asterisk que usuario XMPP está asociado a la extensión que está enviando el mensaje, Con la función MESSAGE_DATA se lee el campo To: del mensaje enviado y luego utilizando la función CUT se extrae solamente el usuario XMPP. Luego se utiliza la aplicación JabberSend para enviar el mensaje al usuario XMPP voztovoice. La sintaxis de la aplicación es:

JabberSend(account,jid,message)

  • account es la cuenta configurada en el archivo xmpp.conf que se utilizará para enviar el mensaje
  • jid es el usuario al que se enviará el mensaje escrito junto al dominio
  • message es el texto del mensaje que se enviará:

Se guardan los cambios y se recarga el dialplan:

asterisk -rvvvvvvvvvvvv

CLI> dialplan reload

Se intenta enviar nuevamente el mensaje desde X-Lite:

Captura

En el cliente Spark:

Captura

El Gateway funciona perfectamente. Ahora la primera pregunta. Si se quiere empezar la chat desde el X-Lite, ¿cómo se hace para enviar el mensaje al usuario voztovoice? Se modifica nuevamente el dialplan y en el contexto utilizado para el monitoreo de las extensiones (en mi caso [subscribe]) se añade la siguiente línea:

exten => voztovoice,hint,custom:voztovoice

es decir que se crea el monitoreo de una extensión personalizada. Se recarga el dialplan y se añade el contacto a la lista de contactos del X-Lite. El resultado:

Captura

Hay que decir que el usuario voztovoice siempre aparecerá en línea ya, que yo sepa, no hay posibilidad de monitorear extensiones XMPP con la prioridad hint. Se podría utilizar la función JABBER_STATUS para saber, antes de enviar el mensaje, si el usuario XMPP se encuentra en línea o no. El problema es que parece que esa función no responde como debería. Esperemos que ese problema se corrija pronto. Mientras vamos sencillamente a enviar el mensaje. Se abre nuevamente el dialplan:

nano /etc/asterisk/extensions.conf

y en el contexto [messages] añadimos el siguiente bloque:

exten => _[a-z].,1,NoOp(mensaje SIP -> XMPP directo)
same => n,NoOp(${MESSAGE(from)})
same => n,Set(from=${CUT(MESSAGE(from),:,2)})
same => n,Set(from=${CUT(from,@,1)})
same => n,Set(from=${DB(ext/${from})})
same => n,JabberSend(${from},${EXTEN}@voztovoice.net,${MESSAGE(body)})
same => n,Hangup

Para que funcione todos los usuarios XMPP deberán tener un nombre que empiece con una letra minúscula. Se guardan los cambios y se recarga el dialplan:

asterisk -rvvvvvvvvvvvvvvvv

CLI> dialplan reload

desde el X-Lite se envía un mensaje al usuario XMPP voztovoice:

Captura

En el cliente Spark:

Captura

La configuración del “Gateway” parece un poco complicada pero la verdad es bastante sencilla.

¿Qué opinan?

Vota el Articulo: 

Sin votos (todavía)
Evalúa la calidad del articulo

1 comentario

sip:Unknown - Usuario SIP desconocido

Hola,

Perdón por mi español (portuñol :-)

En las mensajes desde uno usuario xmpp (maria) hasta uno usuario xmpp en asterisk (juan), el usuario sip (de maria) queda desconocido.

From: "xmpp:maria@servidor.xmpp.externo/laboratorio" (sip:Unknown@servidor.sip.interno)

Entonces las mensajes desde el usuario sip (juan, extension 1020) hasta el el usuario xmpp externo (maria) generan un error 404.

?Que puedo hacer?

Gracias por el post.

Marcio

(--- XMPP received from 'juan' ---)
(message from='maria@servidor.xmpp.externo/laboratorio' to='juan@servidor.xmpp.externo' type='chat' id='purple8c2211d
d')(active xmlns='http://jabber.org/protocol/chatstates'/)(body)00000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000(/body)(/message)
(-------------)
Reliably Transmitting (NAT) to servidor.sip.interno:52764:
MESSAGE sip:1020@192.168.0.105:52764;ob SIP/2.0
Via: SIP/2.0/UDP servidor.sip.interno:5060;branch=z9hG4bK074a16d4;rport
From: "xmpp:maria@servidor.xmpp.externo/laboratorio" (sip:Unknown@servidor.sip.interno);tag=as4425790f
To: (sip:1020@192.168.0.105:52764;ob)

Contact: (sip:Unknown@servidor.sip.interno:5060)

000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000

Suscribirse a Comentarios de "Asterisk 11.X - Mensajes instantáneos SIP &lt;-&gt; XMPP" Suscribirse a VozToVoice - Todos los comentarios