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.