Antes de mostrar de qu� manera es posible verificar el estado de disponibilidad de un usuario dado, debemos explicar algunos de los mecanismos que rigen la red Jabber. Una de sus reglas fundamentales es la de protecci�n de la privacidad de todos y cada uno de sus participantes, por lo que no es posible conocer la disponibilidad de otra persona sin que �sta tenga de ello conocimiento y lo haya aprobado previamente.
Para poder estar al corriente de la presencia de otros participantes de la red, es necesario enviar un comunicado del tipo adecuado solicitando permiso para hacerlo. El usuario en cuesti�n puede, por supuesto, dar o no su consentimiento. La mayor�a de los clientes Jabber pueden ser configurados para que, junto con la aceptaci�n propia, se env�e una solicitud de observaci�n del estado de su remitente. De esta manera se crean relaciones rec�procas, en las que dos usuarios son informados de sus respectivas entradas y salidas de la red.
El estado de un usuario puede tener como m�nimo uno de los dos valores existentes: disponible y no disponible. El estado no disponible no es especialmente interesante: significa que un usuario dado no est� presente en la red. Por otra parte, resulta que es posible estar disponible en mayor o menor medida. Estas diferencias en el estado de disponibilidad permiten al potencial interlocutor saber si en un momento dado estamos demasiado ocupados para conversar o si, al contrario, podemos charlar libremente.
Utilizando un cliente Jabber podemos declarar que estamos:
- disponibles
- disponibles y dispuestos a chatear (ing. free for chat)
- temporalmente lejos del ordenador (ing. temporarily away)
- ausentes por un periodo m�s bien largo (ing. extended away)
- ocupados y pedimos que no se nos moleste (ing. do not disturb)
En el protocolo estos estados son representados, respectivamente, por los siguientes c�digos: [vac�o], chat, away, xa, dnd.
El intercambio de paquetes con estados de disponibilidad puede tener lugar en dos situaciones diferentes:
- inmediatamente despu�s de que un usuario ingrese a la red el servidor le env�a una lista (conocida como roaster) con el estado de cada uno de sus contactos,
- todo cambio de estado de un usuario hace que el servidor env�e una notificaci�n de este hecho a todos los dem�s usuarios en cuyas listas de contacto �ste se encuentre.
Esto implica que existan dos modos diferentes de obtener informaci�n sobre la disponibilidad de un usuario: podemos preguntar directamente al servidor acerca de todos los usuarios de nuestra lista (simplemente iniciando una nueva sesi�n), o esperar a que el servidor nos notifique los cambios de estado que vayan ocurriendo entre nuestros contactos.
Desafortunadamente, ambos modelos tienen sus desventajas desde el punto de vista del programador web. La apertura de una nueva sesi�n de Jabber es una operaci�n que requiere de mucho tiempo, por lo que una p�gina con la lista de contactos cuyo funcionamiento se base en este m�todo podr�a terminar siendo inaceptablemente lenta. La opci�n de esperar notificaciones del servidor tampoco parece ser una salida viable, puesto que una vez visualizada la p�gina web, el entorno PHP desaparece y no queda ning�n proceso que pueda recibir la informaci�n.
Pero existe una manera elegante de resolver estos dos problemas: lanzar desde la consola (en segundo plano, en el servidor web) un proceso independiente de PHP que se ocupe de mantener la comunicaci�n con la red Jabber. De esta manera podemos simular un verdadero cliente que est� continuamente en la memoria y sea capaz de almacenar los resultados de su trabajo en una base de datos. Un cliente as� puede ser utilizado por otros scripts del lado del servidor, los cuales ser�n capaces de hacer uso de las informaciones provenientes de la red Jabber sin necesidad de interactuar directamente con ella. La arquitectura de una soluci�n como la expuesta ha sido presentada en la Figura 2.
![Figura 2: Arquitectura de la solución basada en un script lanzado desde la consola](/cursos_descargas/phpsol_livechat/fig2.gif)
�El programa lanzado desde la consola
Todas estas consideraciones te�ricas pueden parecer demasiado amplias, pero son indispensables para poder analizar y entender el script del Listado 2.
<?php require('lib/jabber/class.jabber.php'); $JABBER = new Jabber; $JABBER->server = 'localhost'; $JABBER->port = '5222'; $JABBER->username = 'www_send'; $JABBER->password = 'www_send'; $JABBER->resource = 'ClassJabberPHP'; $JABBER->Connect() or die('�No puedo conectarme!'); $JABBER->SendAuth() or die('�No puedo autorizarme!'); $JABBER->SendPresence(); $JABBER->CruiseControl(); $JABBER->Disconnect(); function Handler_presence_available($message) { global $JABBER; $jid = $JABBER->StripJID($JABBER->GetInfoFromPresenceFrom($message)); $status = $JABBER->GetInfoFromPresenceShow($message); print "$jid - status: $status"; } function Handler_presence_unavailable($message) { global $JABBER; $jid = $JABBER->StripJID($JABBER->GetInfoFromPresenceFrom($message)); $status = $JABBER->GetInfoFromPresenceShow($message); print "$jid - status: $status"; } ?>
En este listado pueden verse muchos de los elementos que ya conocemos: el establecimiento de la conexi�n con el servidor, la autorizaci�n... En realidad, la �nica �novedad� es la invocaci�n del m�todo $JABBER->CruiseControl() y la definici�n de dos nuevas funciones: Handler_presence_available($message) y�Handler_presence_unavailable($message).
Los nombres de las nuevas funciones indican claramente cu�l es su uso: las llama la clase ClassJabberPHP en respuesta a ciertos comunicados recibidos de la red Jabber (en concreto a los que contienen informaci�n acerca del estado de disponibilidad de otros usuarios). El m�todo CruiseControl() es una manera de decir �desde este momento escucha y si aparece alg�n comunicado, invoca la funci�n apropiada (ing. handler) para el manejo del tipo de comunicado recibido�.
Una vez las informaciones sobre el estado de disponibilidad de los usuarios que nos interesan se encuentran en la base de datos, la creaci�n de un script que nos permita visualizarlas no representa para nosotros mayor problema.
�Recepci�n de mensajes
Nuestro programa sabe ya hablar (puede enviar mensajes � Listado 1) y ver (puede observar los estados de otros usuarios � Listado 2). De la conversaci�n plena nos separa s�lo un paso: la posibilidad de escuchar. Se trata de una tarea bastante sencilla si recordamos la manera en que le�amos las informaciones acerca de los estados de disponibilidad: en este caso tambi�n debemos crear una funci�n-handler que se encargue de recibir los comunicados de tipo mensaje (ing. message). El fragmento de c�digo presentado en el Listado 3 es bastante ilustrativo de c�mo se hace esto en la pr�ctica.
... function Handler_message_chat($message) { global $db; global $JABBER; $msg = $JABBER->GetInfoFromMessageBody($message); $thread = $JABBER->GetInfoFromMessageThread($message); $sql = 'INSERT INTO jabber_messages (sid, msg) VALUES ("'.$thread.'", "'.$msg.'")'; if (!$db->Execute($sql)) { die ('Error de acceso a la base de datos!'); } } ...
N�tese c�mo el mensaje recibido se introduce inmediatamente en la base de datos (igual que como lo hicimos con la informaci�n sobre la disponibilidad), por lo que el script para visualizar mensajes en una p�gina web resulta muy sencillo de escribir y es totalmente independiente de los servicios Jabber. Adem�s, esto nos permite conservar el historial completo de las conversaciones realizadas.