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.