El protocolo Yar

Yar no depende de un esquema ni de un fichero IDL: todo se intercambia por la red como bytes sin formato. Cualquier lenguaje capaz de leer y escribir bytes puede comunicarse con un servicio Yar, sin instalar ningún framework —basta con construir una cabecera binaria de tamaño fijo y un cuerpo de petición serializado, enviarlos al URI del servicio y analizar la respuesta.

Un mensaje consta de una cabecera de tamaño fijo de 82 bytes seguida de un cuerpo. La cabecera tiene exactamente la disposición de la siguiente estructura C, empaquetada sin relleno, y se escribe en la red campo a campo en el orden de declaración:

typedef struct _yar_header {
    uint32_t       id;            /* identificador de la transacción */
    uint16_t       version;       /* versión del protocolo, actualmente siempre 0 */
    uint32_t       magic_num;     /* debe ser 0x80DFEC60 */
    uint32_t       reserved;
    unsigned char  provider[32];  /* de quién procede la petición (autenticación) */
    unsigned char  token[32];     /* token de la petición (autenticación) */
    uint32_t       body_len;      /* longitud del cuerpo completo, incluido
                                     el identificador del empaquetador */
} __attribute__ ((packed)) yar_header_t;

Los campos id, magic_num, reserved y body_len se almacenan en el orden de bytes de red (big-endian); los campos restantes son bytes sin formato.

El cuerpo comienza con un identificador de empaquetador de 8 bytes —PHP, JSON o MSGPACK, rellenado con ceros— que indica al receptor cómo se ha codificado el resto, seguido del propio contenido serializado.

  • El cuerpo de la petición se decodifica en un array con las claves i (el identificador de la transacción), m (el método invocado) y p (la lista de parámetros).

  • El cuerpo de la respuesta se decodifica en un array con las claves i (el identificador de la transacción), s (el estado, uno de los códigos YAR_ERR_*), r (el valor devuelto), o (la salida producida por el método del servicio) y e (el error o la excepción, cuando la llamada ha fallado).

Sobre HTTP, el mensaje se envía como cuerpo de una petición POST, y la respuesta llega como cuerpo de la contestación; sobre TCP o sockets Unix se escribe directamente en el flujo.

Ejemplo #1 Llamada a un servicio Yar sin la extensión

El siguiente script autónomo construye una petición Yar válida para el empaquetador php únicamente con sockets estándar, la envía al URI de un servicio y muestra la respuesta decodificada. Al ejecutarlo contra el servicio Operator de los ejemplos, muestra int(3).

<?php

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

/* 1. el cuerpo: identificador del empaquetador + petición serializada */
$serialized = serialize(array("i" => 1, "m" => "add", "p" => array(1, 2)));
$body = str_pad("PHP", 8, "\0") . $serialized;

/* 2. la cabecera: 82 bytes, enteros multibyte en orden de bytes de red */
$header = pack("N", 1)                    /* id */
        . pack("v", 0)                    /* versión */
        . pack("N", 0x80DFEC60)           /* número mágico */
        . pack("N", 0)                    /* reservado */
        . str_pad("", 32, "\0")           /* proveedor */
        . str_pad("", 32, "\0")           /* token */
        . pack("N", strlen($body));       /* longitud del cuerpo */

/* 3. se envía como cuerpo de una petición 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. se analiza la respuesta: cabecera de 82 bytes, luego el cuerpo */
$response = unserialize(substr($reply, 82 + 8));
var_dump($response["r"]);
?>

En el directorio tools/ del » repositorio de código fuente de Yar se encuentra una implementación de cliente más completa en PHP puro, que además decodifica la cabecera de la respuesta y admite llamadas concurrentes.

add a note

User Contributed Notes

There are no user contributed notes for this page.