User Tools

Site Tools


fr:dev:moxl:xec

XEC

XEC (pour XMPP Event Controller) est un sous module de Moxl. Il permet de gérer intelligemment les requêtes passées au travers de Moxl. XEC se subdivise lui-même en deux grandes parties ; les Actions et les Payloads.

Dans les deux cas les XECPayload et XECHandler sont à développer par l'intégrateur pour lier les événements de Moxl à ceux de l'application cible.

Action

Une action XEC est un requête faite sur le serveur XMPP. Ici XEC introduit un système permettant à Moxl de se “souvenir” de requêtes passées et ainsi de renvoyer la réponse à l'endroit dans le code où la requête a été lancée.

namespace Moxl\Xec\Action\Roster;
 
use Moxl\Xec\Action;
use Moxl\Stanza\Roster
 
class AddItem extends Action
{
    private $_to;
 
    public function request() 
    {
        $this->store();
        Roster::add($this->_to);
    }
 
    public function setTo($to)
    {
        $this->_to = $to;
        return $this;
    }
 
    public function handle($stanza) 
    {
        var_dump('Handle item');
    }
 
    public function errorServiceUnavailable() 
    {
        var_dump('Handle the Error !');
    }
}

Cet exemple montre l'action “ajout d'un contact à la liste de contacts”, cette action hérite de XECAction. Pour ajouter un contact on pourra alors l'appeler ainsi :

use Moxl\Xec\Action\Roster\AddItem;
 
$c = new AddItem();
$c->setTo('contact@serveur.com')
  ->request();

Notez que la ligne

$this->store();

est obligatoire pour demander à XEC d'initialiser la requête pour plus tard gérer sa réponse.

Système de requêtes

L'action store() va permettre de sauvegarder l'instance au moment de donné et va la stocker dans un tableau comprenant toutes les demandes en cours, cette instance sera numérotée avec le numéro de la requête XMPP.

Au retour, XECHandler vérifie si l'identifiant de la stanza existe dans le tableau et réinstancie la classe en question. Ainsi le développeur ne sera même pas au courant que la requête et la réponse ont eu lieu en deux exécutions (via deux requêtes différentes sur le serveur XMPP). La requête partant dans la méthode request() et revenant dans la méthode handle() de la même instance.

Réponse

Si tout se passe bien la réponse à la requête arrivera dans la méthode handle($stanza), $stanza étant la réponse convertie au format SimpleXML.

Les valeurs des attributs de la classe sont aussi sauvegardés et restitués quand la bonne réponse revient, libre à vous de jouer avec ça si vous souhaitez conserver certaines valeurs entre la requête et la réponse.

Gestion des erreurs

Tout comme pour les bonnes réponses il peut aussi arriver que la requête en question se solde par une erreur du coté XMPP. XEC gère intelligemment ce retour d'erreur et tente d'appeler au sein de la classe appelante la méthode correspondant au nom de l'erreur retournée (convertie au format CamelCase).

Libre à vous de traiter, ou non, certaines de ces erreurs. Elles sont, dans tout les cas, loggées via syslog dans /var/log/user.log. Dans l'exemple ci-dessus nous avons donc la méthode permettant de traiter l'erreur errorServiceUnavailable. Ce système de gestion d'erreur est intéressant, il pourra en effet permettre de notifier intelligemment l'utilisateur d'une mauvaise manipulation directement sur son navigateur (comme le fait Movim actuellement).

Payload

Les payloads, sont “l'inverse” des actions ; ce sont les stanzas envoyées par le serveur sans requête de la part du client (ici Moxl). Les messages envoyés par les contacts lors d'une discussion en sont un exemple typique. De la même façon que pour un retour d'action, Moxl essaye de comprendre intelligemment de quelle stanza il s'agit au travers de XEC.

Le fonctionnement est ici un peu différent. Voici un petit extrait de XECHandler, il s'agit de la partie s'occupant du hashage des stanzas de type payload.

require('XECHandler.array.php');
 
$name = $s->getName();
$ns = $s->getNamespaces();
$node = (string)$s->attributes()->node;
 
if(is_array($ns))
    $ns = current($ns);
 
$hash = md5($name.$ns.$node);
 
MoxlLogger::log('XECHandler : Searching a payload for "'.$name . ':' . $ns . ' [' . $node . ']", "'.$hash.'"');

Concrètement ici, XECHandler va générer un hash unique par “type” de payload à partir de 3 données :

  • name : le nom de la stanza
  • ns : le namespace de la stanza
  • node : le nom de l'attribut “node” s'il existe (le plus souvent vide mais indispensable pour des payloads venant de nœuds pubsub particuliers).

Exemple

L'arrivée d'un post publié par un contact sur son flux microblogging a toujours cette forme

<event xmlns='http://jabber.org/protocol/pubsub#event'>
  <items node='urn:xmpp:microblog:0'>
    <item id='1cb57d9c-1c46-11dd-838c-001143d5d5db' publisher='romeo@montague.lit'>
     <entry xmlns='http://www.w3.org/2005/Atom'>
       <title type='text'>hanging out at the Caf&amp;#233; Napolitano</title>
       <link rel='alternate'
             type='text/html'
             href='http://montague.lit/romeo/posts/1cb57d9c-1c46-11dd-838c-001143d5d5db'/>
       <link rel='alternate'
             href='xmpp:romeo@montague.lit?;node=urn%3Axmpp%3Amicroblog%3A0;item=1cb57d9c-1c46-11dd-838c-001143d5d5db'/>
       <id>tag:montague.lit,2008-05-08:posts-1cb57d9c-1c46-11dd-838c-001143d5d5db</id>
       <published>2008-05-08T18:30:02Z</published>
       <updated>2008-05-08T18:30:02Z</updated>
     </entry>
   </item>
</event>
</items>

Ici nous aurons donc :

XECHandler va donc faire un hash MD5 de $name.$ns.$node puis regarder dans le tableau contenu dans le fichier XECHandler.array.php pour essayer de trouver une correspondance.

Ici le hash MD5 des trois valeurs donne '96c06e02022480352b6c581286b7eefb'.

$hashToClass = array(
    '9b98cd868d07fb7f6d6cb39dad31f10e' => 'Message',
    'e83b2aea042b74b1bec00b7d1bba2405' => 'Presence',
 
    '96c06e02022480352b6c581286b7eefb' => 'Post'
    );

S'il trouve une clef correspondante dans le tableau il tentera d'instancier la classe en question et d'appeler la méthode handle().

namespace Moxl\Xec\Payload;
 
class Post extends Payload
{
    public function handle($stanza) {   
        var_dump('Post received');
    }
}

Ici tout Post de type Microblog tombera donc dans cette classe, libre au développeur de faire ce qu'il souhaite avec la $stanza passée en paramètre.

Recherche en profondeur

La recherche de Handlers adéquats ne se fait pas que sur un seul niveau, comme vous avez pu le remarquer dans l'exemple précédent. XECHandler va également rechercher au sein des stanzas pour essayer de détecter des sous informations qui pourraient intéresser le développeur et lever des événements sur celles-ci.

La recherche en profondeur se limite à trois niveaux maximum (correspondant à trois niveaux de XML imbriqués), en partie pour des soucis de performance.

Packet, communication avec Movim

Afin de standardiser et d'unifier les événements envoyés à Movim, les Actions et les Payloads ont tous deux la possibilité d’émettre des Packets ayant une clef unique et générée par Moxl.

Ces Packets peuvent être émis depuis la méthode handle ou les méthodes de gestion d'erreur.

Exemple

Étudions l'exemple suivant afin de comprendre comment ce système fonctionne.

namespace Moxl\Xec\Payload;
 
class SASLFailure extends Payload
{
    public function handle($stanza, $parent = false) {
        $session = \Sessionx::start();
        $session->destroy();
 
        $this->pack($stanza->children()->getName());
        $this->deliver();
    }
}

Ce Payload gère le cas d'une authentification SASL ayant échoué. Suite à la destruction de la session, deux méthodes relatives au système de Packets sont utilisées.

  1. $this→pack() s'occupe d'empaqueter l'information que nous souhaitons transmettre à Movim. Elle peut ne pas avoir de type défini (booléen, chaîne, objet). Évitez tout de même de transmettre de trop grosses informations afin de ne pas surcharger le démon.
  2. $this→deliver() envoie le paquet au gestionnaire d’événements de Movim.

Génération des clefs

Packet va s'occuper de générer automatiquement la clef permettant de trier les paquets au sein de Movim. Ces événements seront reçus au sein des widgets intéressés comme décrit sur la page Environnement d'exécution.

Cette clef est générée suivant deux schémas relatifs aux Actions et Payloads.

Pour les Actions

[dernier espace de nom]_[nom de la classe]_[méthode] en minuscule.

Dans le cas d'une action Moxl\Xec\Action\Vcard\Get réussie nous aurons donc : vcard_get_handle. Si une erreur a été reçue nous appliquons le même schéma : vcard_get_erroritemnotfound.

Pour les Payloads

[nom de la classe]_[méthode] en minuscule.

Pour notre exemple, la clef sera donc : saslfailure_handle.

fr/dev/moxl/xec.txt · Last modified: 2014/11/21 14:09 by nodpounod