<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/book.yar.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'es',
  ),
  'this' => 
  array (
    0 => 'yar.protocol.php',
    1 => 'El protocolo Yar',
    2 => 'El protocolo Yar',
  ),
  'up' => 
  array (
    0 => 'book.yar.php',
    1 => 'Yar',
  ),
  'prev' => 
  array (
    0 => 'book.yar.php',
    1 => 'Yar',
  ),
  'next' => 
  array (
    0 => 'yar.setup.php',
    1 => 'Instalaci&oacute;n/Configuraci&oacute;n',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'es',
    'path' => 'reference/yar/protocol.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="yar.protocol" class="chapter">
 <h1 class="title">El protocolo Yar</h1>

 <p class="simpara">
  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.
 </p>
 <p class="simpara">
  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:
 </p>
 <div class="example-contents">
<div class="ccode"><pre class="ccode">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;</pre>
</div>
 </div>

 <p class="simpara">
  Los campos <code class="literal">id</code>, <code class="literal">magic_num</code>,
  <code class="literal">reserved</code> y <code class="literal">body_len</code> se almacenan
  en el orden de bytes de red (big-endian); los campos restantes son
  bytes sin formato.
 </p>
 <p class="simpara">
  El cuerpo comienza con un identificador de empaquetador de 8 bytes
  —<code class="literal">PHP</code>, <code class="literal">JSON</code> o
  <code class="literal">MSGPACK</code>, rellenado con ceros— que indica al receptor
  cómo se ha codificado el resto, seguido del propio contenido
  serializado.
 </p>
 <ul class="itemizedlist">
  <li class="listitem">
   <p class="simpara">
    El cuerpo de la petición se decodifica en un array con las claves
    <code class="literal">i</code> (el identificador de la transacción),
    <code class="literal">m</code> (el método invocado) y <code class="literal">p</code> (la
    lista de parámetros).
   </p>
  </li>
  <li class="listitem">
   <p class="simpara">
    El cuerpo de la respuesta se decodifica en un array con las claves
    <code class="literal">i</code> (el identificador de la transacción),
    <code class="literal">s</code> (el estado, uno de los códigos
    <code class="literal">YAR_ERR_*</code>), <code class="literal">r</code> (el valor
    devuelto), <code class="literal">o</code> (la salida producida por el método
    del servicio) y <code class="literal">e</code> (el error o la excepción, cuando
    la llamada ha fallado).
   </p>
  </li>
 </ul>
 <p class="simpara">
  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.
 </p>
 <div class="example" id="example-1">
  <p><strong>Ejemplo #1 Llamada a un servicio Yar sin la extensión</strong></p>
  <div class="example-contents"><p>
   El siguiente script autónomo construye una petición Yar válida para el
   empaquetador <code class="literal">php</code> únicamente con sockets estándar, la
   envía al URI de un servicio y muestra la respuesta decodificada. Al
   ejecutarlo contra el servicio <span class="classname"><strong class="classname">Operator</strong></span> de los
   <a href="yar.examples.php" class="link">ejemplos</a>, muestra
   <code class="literal">int(3)</code>.
  </p></div>
  <div class="example-contents">
<div class="phpcode"><pre><code style="color: #000000"><span style="color: #0000BB">&lt;?php

$uri </span><span style="color: #007700">= </span><span style="color: #DD0000">"http://api.example.com/operator.php"</span><span style="color: #007700">;

</span><span style="color: #FF8000">/* 1. el cuerpo: identificador del empaquetador + petición serializada */
</span><span style="color: #0000BB">$serialized </span><span style="color: #007700">= </span><span style="color: #0000BB">serialize</span><span style="color: #007700">(array(</span><span style="color: #DD0000">"i" </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">1</span><span style="color: #007700">, </span><span style="color: #DD0000">"m" </span><span style="color: #007700">=&gt; </span><span style="color: #DD0000">"add"</span><span style="color: #007700">, </span><span style="color: #DD0000">"p" </span><span style="color: #007700">=&gt; array(</span><span style="color: #0000BB">1</span><span style="color: #007700">, </span><span style="color: #0000BB">2</span><span style="color: #007700">)));
</span><span style="color: #0000BB">$body </span><span style="color: #007700">= </span><span style="color: #0000BB">str_pad</span><span style="color: #007700">(</span><span style="color: #DD0000">"PHP"</span><span style="color: #007700">, </span><span style="color: #0000BB">8</span><span style="color: #007700">, </span><span style="color: #DD0000">"\0"</span><span style="color: #007700">) . </span><span style="color: #0000BB">$serialized</span><span style="color: #007700">;

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

/* 3. se envía como cuerpo de una petición POST */
</span><span style="color: #0000BB">$stream </span><span style="color: #007700">= </span><span style="color: #0000BB">stream_context_create</span><span style="color: #007700">(array(</span><span style="color: #DD0000">"http" </span><span style="color: #007700">=&gt; array(
    </span><span style="color: #DD0000">"method"  </span><span style="color: #007700">=&gt; </span><span style="color: #DD0000">"POST"</span><span style="color: #007700">,
    </span><span style="color: #DD0000">"header"  </span><span style="color: #007700">=&gt; </span><span style="color: #DD0000">"Content-Type: application/octet-stream\r\n"</span><span style="color: #007700">,
    </span><span style="color: #DD0000">"content" </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">$header </span><span style="color: #007700">. </span><span style="color: #0000BB">$body</span><span style="color: #007700">,
)));
</span><span style="color: #0000BB">$reply </span><span style="color: #007700">= </span><span style="color: #0000BB">file_get_contents</span><span style="color: #007700">(</span><span style="color: #0000BB">$uri</span><span style="color: #007700">, </span><span style="color: #0000BB">false</span><span style="color: #007700">, </span><span style="color: #0000BB">$stream</span><span style="color: #007700">);

</span><span style="color: #FF8000">/* 4. se analiza la respuesta: cabecera de 82 bytes, luego el cuerpo */
</span><span style="color: #0000BB">$response </span><span style="color: #007700">= </span><span style="color: #0000BB">unserialize</span><span style="color: #007700">(</span><span style="color: #0000BB">substr</span><span style="color: #007700">(</span><span style="color: #0000BB">$reply</span><span style="color: #007700">, </span><span style="color: #0000BB">82 </span><span style="color: #007700">+ </span><span style="color: #0000BB">8</span><span style="color: #007700">));
</span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$response</span><span style="color: #007700">[</span><span style="color: #DD0000">"r"</span><span style="color: #007700">]);
</span><span style="color: #0000BB">?&gt;</span></code></pre></div>
  </div>

 </div>
 <p class="simpara">
  En el directorio <code class="literal">tools/</code> del
  <a href="https://github.com/laruence/yar" class="link external">&raquo;&nbsp;repositorio de código
  fuente de Yar</a> 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.
 </p>
</div>
<?php manual_footer($setup); ?>