<?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 => 'en',
  ),
  'this' => 
  array (
    0 => 'yar.protocol.php',
    1 => 'The Yar Protocol',
    2 => 'The Yar Protocol',
  ),
  'up' => 
  array (
    0 => 'book.yar.php',
    1 => 'Yar',
  ),
  'prev' => 
  array (
    0 => 'book.yar.php',
    1 => 'Yar',
  ),
  'next' => 
  array (
    0 => 'yar.setup.php',
    1 => 'Installing/Configuring',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'en',
    '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">The Yar Protocol</h1>

 <p class="simpara">
  Yar does not rely on a schema or IDL file: everything is exchanged on
  the wire as plain bytes. Any language that can read and write bytes
  can speak to a Yar service, without installing any framework at all —
  build one fixed-size binary header and a serialized request body,
  send them to the service URI, and parse the reply.
 </p>
 <p class="simpara">
  A message consists of a fixed-size header of 82 bytes followed by a
  body. The header is laid out exactly like the following C structure,
  packed with no padding, and is written to the wire field after field
  in declaration order:
 </p>
 <div class="example-contents">
<div class="ccode"><pre class="ccode">typedef struct _yar_header {
    uint32_t       id;            /* transaction id */
    uint16_t       version;       /* protocol version, currently always 0 */
    uint32_t       magic_num;     /* must be 0x80DFEC60 */
    uint32_t       reserved;
    unsigned char  provider[32];  /* request from whom (authentication) */
    unsigned char  token[32];     /* request token (authentication) */
    uint32_t       body_len;      /* length of the whole body, including
                                     the packager identifier */
} __attribute__ ((packed)) yar_header_t;</pre>
</div>
 </div>

 <p class="simpara">
  The <code class="literal">id</code>, <code class="literal">magic_num</code>,
  <code class="literal">reserved</code> and <code class="literal">body_len</code> fields
  are stored in network byte order (big-endian); the remaining fields
  are raw bytes.
 </p>
 <p class="simpara">
  The body starts with an 8-byte packager identifier —
  <code class="literal">PHP</code>, <code class="literal">JSON</code> or
  <code class="literal">MSGPACK</code>, zero-padded — telling the receiver how
  the remainder was encoded, followed by the serialized content itself.
 </p>
 <ul class="itemizedlist">
  <li class="listitem">
   <p class="simpara">
    The request body decodes to an array with the keys
    <code class="literal">i</code> (the transaction id), <code class="literal">m</code>
    (the method being called) and <code class="literal">p</code> (the list of
    parameters).
   </p>
  </li>
  <li class="listitem">
   <p class="simpara">
    The response body decodes to an array with the keys
    <code class="literal">i</code> (the transaction id), <code class="literal">s</code>
    (the status, one of the <code class="literal">YAR_ERR_*</code> codes),
    <code class="literal">r</code> (the return value), <code class="literal">o</code> (any
    output the service method produced) and <code class="literal">e</code> (the
    error or exception, when the call failed).
   </p>
  </li>
 </ul>
 <p class="simpara">
  Over HTTP the message is sent as the body of a POST request, with
  the response arriving as the body of the reply; over TCP or Unix
  sockets it is written directly on the stream.
 </p>
 <div class="example" id="example-1">
  <p><strong>Example #1 Calling a Yar service without the extension</strong></p>
  <div class="example-contents"><p>
   The following self-contained script builds a valid Yar request for
   the <code class="literal">php</code> packager with nothing but standard
   sockets, sends it to a service URI, and prints the decoded
   response. Running it against the
   <span class="classname"><strong class="classname">Operator</strong></span> service from the
   <a href="yar.examples.php" class="link">examples</a> prints
   <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. the body: packager identifier + serialized request */
</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. the header: 82 bytes, multi-byte integers in network byte order */
</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">/* version */
        </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">/* magic number */
        </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">/* reserved */
        </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">/* provider */
        </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">/* body length */

/* 3. send it as the body of a POST request */
</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. parse the reply: 82-byte header, then the response body */
</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">
  A more complete client implementation in plain PHP, which also
  decodes the response header and supports concurrent calls, lives in
  the <code class="literal">tools/</code> directory of the
  <a href="https://github.com/laruence/yar" class="link external">&raquo;&nbsp;Yar source
  repository</a>.
 </p>
</div>
<?php manual_footer($setup); ?>