PHP 8.5.10 Released!

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.
To Top