Le protocole Yar

Yar ne s'appuie pas sur un schĂ©ma ou un fichier IDL : tout est Ă©changĂ© sur le rĂ©seau sous forme d'octets bruts. N'importe quel langage capable de lire et d'Ă©crire des octets peut communiquer avec un service Yar, sans installer aucun framework — il suffit de construire un en-tĂȘte binaire de taille fixe et un corps de requĂȘte sĂ©rialisĂ©, de les envoyer Ă  l'URI du service, et d'analyser la rĂ©ponse.

Un message se compose d'un en-tĂȘte de taille fixe de 82 octets suivi d'un corps. L'en-tĂȘte est disposĂ© exactement comme la structure C suivante, compactĂ©e sans remplissage, et est Ă©crit sur le rĂ©seau champ aprĂšs champ dans l'ordre de dĂ©claration :

typedef struct _yar_header {
    uint32_t       id;            /* identifiant de transaction */
    uint16_t       version;       /* version du protocole, toujours 0 actuellement */
    uint32_t       magic_num;     /* doit valoir 0x80DFEC60 */
    uint32_t       reserved;
    unsigned char  provider[32];  /* Ă©metteur de la requĂȘte (authentification) */
    unsigned char  token[32];     /* jeton de la requĂȘte (authentification) */
    uint32_t       body_len;      /* longueur du corps entier, y compris
                                     l'identifiant d'empaqueteur */
} __attribute__ ((packed)) yar_header_t;

Les champs id, magic_num, reserved et body_len sont stockés dans l'ordre réseau (gros-boutiste) ; les champs restants sont des octets bruts.

Le corps commence par un identifiant d'empaqueteur de 8 octets — PHP, JSON ou MSGPACK, complĂ©tĂ© par des zĂ©ros — indiquant au destinataire comment le reste a Ă©tĂ© encodĂ©, suivi du contenu sĂ©rialisĂ© lui-mĂȘme.

  • Le corps de requĂȘte se dĂ©code en un tableau avec les clĂ©s i (l'identifiant de transaction), m (la mĂ©thode appelĂ©e) et p (la liste des paramĂštres).

  • Le corps de rĂ©ponse se dĂ©code en un tableau avec les clĂ©s i (l'identifiant de transaction), s (le statut, l'un des codes YAR_ERR_*), r (la valeur de retour), o (toute sortie produite par la mĂ©thode du service) et e (l'erreur ou l'exception, quand l'appel a Ă©chouĂ©).

En HTTP le message est envoyĂ© comme corps d'une requĂȘte POST, la rĂ©ponse arrivant comme corps de la rĂ©ponse ; en TCP ou socket Unix il est Ă©crit directement sur le flux.

Exemple #1 Appel d'un service Yar sans l'extension

Le script autonome suivant construit une requĂȘte Yar valide pour l'empaqueteur php avec uniquement des sockets standard, l'envoie Ă  un URI de service et affiche la rĂ©ponse dĂ©codĂ©e. ExĂ©cutĂ© contre le service Operator des exemples, il affiche int(3).

<?php

$uri = "http://api.example.com/operator.php";

/* 1. le corps : identifiant d'empaqueteur + requĂȘte sĂ©rialisĂ©e */
$serialized = serialize(array("i" => 1, "m" => "add", "p" => array(1, 2)));
$body = str_pad("PHP", 8, "\0") . $serialized;

/* 2. l'en-tĂȘte : 82 octets, entiers multi-octets dans l'ordre rĂ©seau */
$header = pack("N", 1)                    /* id */
        . pack("v", 0)                    /* version */
        . pack("N", 0x80DFEC60)           /* nombre magique */
        . pack("N", 0)                    /* reserved */
        . str_pad("", 32, "\0")           /* provider */
        . str_pad("", 32, "\0")           /* token */
        . pack("N", strlen($body));       /* longueur du corps */

/* 3. l'envoyer comme corps d'une requĂȘte POST */
$stream = stream_context_create(array("http" => array(
    "method"  => "POST",
    "header"  => "Content-Type: application/octet-stream\r\n",
    "content" => $header . $body,
)));
$reply = file_get_contents($uri, false, $stream);

/* 4. analyser la rĂ©ponse : en-tĂȘte de 82 octets, puis le corps */
$response = unserialize(substr($reply, 82 + 8));
var_dump($response["r"]);
?>

Une implĂ©mentation client plus complĂšte en PHP pur, qui dĂ©code Ă©galement l'en-tĂȘte de rĂ©ponse et supporte les appels concurrents, se trouve dans le rĂ©pertoire tools/ du » dĂ©pĂŽt source de Yar.

add a note

User Contributed Notes

There are no user contributed notes for this page.