2023-02-17 09:22:27 +00:00
|
|
|
{% extends "sega.html" %} {% block title %}PCP{% endblock %} {% block body %}
|
2022-06-13 02:41:05 +00:00
|
|
|
<h1>PCP</h1>
|
|
|
|
<h2>What is PCP?</h2>
|
2023-02-17 09:22:27 +00:00
|
|
|
<p>
|
|
|
|
PCP is the protocol used for inter-process communication between services running on Ring* systems. I have no idea
|
|
|
|
what it stands for; head-canon it as Process Communication Protocol or whatever you want really. The official
|
|
|
|
implementation is <code>libpcp</code>, which is statically linked in to binaries that make use of the protocol (and
|
|
|
|
is itself dependent on <code>amLib</code>).
|
|
|
|
</p>
|
|
|
|
<p>
|
|
|
|
On paper, there are many things the format would at first appear to support, but is unable to due to the reference
|
|
|
|
implementation in <code>libpcp</code>. Specification of this nature will be <span class="mark">marked</span>. Custom
|
|
|
|
implementations should be liberal in what they receive, and conservative in what they transmit; marked specification
|
|
|
|
are key areas of focus for this.
|
|
|
|
</p>
|
2022-06-13 02:41:05 +00:00
|
|
|
|
|
|
|
<h2>Protocol Specification</h2>
|
2023-02-17 09:22:27 +00:00
|
|
|
<p>
|
|
|
|
We consider two processes communicating: a server, and a consumer. A server need only be capable of processing at
|
|
|
|
least one consumer concurrently, though implementations may desire the ability to process multiple consumers.
|
|
|
|
</p>
|
|
|
|
<p>
|
|
|
|
When a server is ready to process a command, it transmits a single <code>></code> byte to its connected consumer.
|
2022-06-13 02:41:05 +00:00
|
|
|
</p>
|
|
|
|
<p>The consumer responds with a CRLF-terminated payload packet, containing the command.</p>
|
2023-02-17 09:22:27 +00:00
|
|
|
<p>
|
|
|
|
The server then responds syncronously with a CRLF-terminated payload packet. If a data transfer is being a
|
|
|
|
performed, this packet will contain <code>port</code> and <code>size</code> as paramaters.
|
|
|
|
</p>
|
|
|
|
<p>
|
|
|
|
In a server->consumer data transfer operation, the consumer connects to the provided port, and expects to receive
|
2022-06-13 02:41:05 +00:00
|
|
|
<code>size</code> bytes of data. It then closes the connection to the data port and transmits a <code>$</code> byte
|
|
|
|
to the server to ackgnowledge receipt. The server will only process this ackgnowledgement after it has succesfully
|
|
|
|
transmitted its data to a consumer.
|
|
|
|
</p>
|
|
|
|
<p>The characteristics of a consumer->server transfer as as yet undocumented. I'll get round to it!</p>
|
|
|
|
|
2023-02-17 09:22:27 +00:00
|
|
|
<p>
|
|
|
|
If the server is unable to process a request for any reason, it may respond with a single <code>?</code>. This may
|
|
|
|
be due to a non existant command being requested, or it may be due to an invalid packet.
|
|
|
|
</p>
|
2022-06-13 02:41:05 +00:00
|
|
|
|
|
|
|
<h3>Payload format</h3>
|
2023-02-17 09:22:27 +00:00
|
|
|
|
|
|
|
<p>
|
|
|
|
Outside of special packets such as <code>></code> and <code>$</code>, all communication in both directions
|
|
|
|
strictly follows the following structure:
|
2022-06-13 02:41:05 +00:00
|
|
|
</p>
|
2023-02-17 09:22:27 +00:00
|
|
|
|
|
|
|
<img src="{{ROOT}}/images/pcp-railroad.png" class="graphic" />
|
|
|
|
|
|
|
|
<p>
|
|
|
|
<i><code>Text</code></i> is defined as a series of one or more bytes matching <code>[a-zA-Z0-9._:@%/\{}-]</code>.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
Spaces (ascii 20<sub>h</sub>) and tabs (ascii 09<sub>h</sub>) are allowable whitespace. They may be present anywhere
|
2022-06-13 02:41:05 +00:00
|
|
|
in the packet surrounding keys, values, any delimiter, or seperator, and will be ignored. They are not valid within
|
2023-02-17 09:22:27 +00:00
|
|
|
a key or a value.
|
|
|
|
</p>
|
|
|
|
<p>
|
|
|
|
Comments begin and end with the <code>#</code> symbol. They may appear at any point in a packet, and the packet
|
|
|
|
should be processed as if the comment is not there.
|
|
|
|
<b
|
|
|
|
>The content of comments must match <i><code>Text</code></i
|
|
|
|
>. This notably includes no whitespace.</b
|
|
|
|
>
|
|
|
|
</p>
|
2022-06-13 02:41:05 +00:00
|
|
|
|
|
|
|
<h2>Format restrictions</h2>
|
|
|
|
<ul>
|
|
|
|
<li><span class="mark">Payloads MUST NOT exceed 256 bytes, including the terminating CRLF.</span></li>
|
|
|
|
<li><span class="mark">There may be at most 64 key-value pairs in a payload.</span></li>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<h2>Example communication</h2>
|
|
|
|
<p>Communication from the server is marked in blue, and communication from the client is marked in red.</p>
|
|
|
|
<pre><code><span class="server">></span><span class="client">nonsense
|
|
|
|
</span><span class="server">?
|
|
|
|
></span><span class="client">keychip.version=?&device=n2&cache=0
|
|
|
|
</span><span class="server">keychip.version=0104
|
|
|
|
></span><span class="client">keyc#comment#hip.version=?
|
|
|
|
</span><span class="server">keychip.version=0104
|
|
|
|
></span><span class="client">keychip.billing.cacertification=?
|
|
|
|
</span><span class="server">keychip.billing.cacertification=0&port=40107&size=817
|
|
|
|
</span><span class="client">$</span><span class="server">></span></code></pre>
|
|
|
|
<p>(Note an additional connection was made to <code>:40107</code> before transmitting the <code>$</code>.)</p>
|
|
|
|
|
|
|
|
<details>
|
|
|
|
<summary>libpcp bugs</summary>
|
2023-02-17 09:22:27 +00:00
|
|
|
<p>
|
|
|
|
When parsing requests, libpcp null-terminates <code>?</code> values with an off-by-one error. This means if you
|
2022-06-13 02:41:05 +00:00
|
|
|
transmit <code>test=12345</code> followed by <code>test=?</code>, it will be parsed as if you had transmitted
|
|
|
|
<code>test=?2</code>. This could actually be an issue with how I am inspecting the internal state; I will
|
|
|
|
update/remove this spoilier once I've had a chance to dig deeper.
|
|
|
|
</p>
|
2023-02-17 09:22:27 +00:00
|
|
|
<p>
|
|
|
|
libpcp does not enforce ampersand placement, causing strange memory artifacts. Consumers <b>MUST</b> conform to
|
|
|
|
the ampersand specification.
|
|
|
|
</p>
|
|
|
|
<p>
|
|
|
|
libpcp allows empty keys and values. The case of an empty key causes the pair to be keyed with an empty string,
|
2022-06-13 02:41:05 +00:00
|
|
|
however an empty value causes it to contain a random value, reading from memory where the previous packet was
|
|
|
|
decoded. In fact, the presence of a <code>=</code> is not validated either, likewise causing it to read
|
2023-02-17 09:22:27 +00:00
|
|
|
undefined regions of memory. Consumers <b>MUST</b> always provide both the key and the value.
|
|
|
|
</p>
|
2022-06-13 02:41:05 +00:00
|
|
|
</details>
|
|
|
|
<details>
|
|
|
|
<summary>Using libpcp</summary>
|
2023-02-17 09:22:27 +00:00
|
|
|
<p>
|
|
|
|
I have reproduced a locally functioning standalone distribution of libpcp, warts and all. Eventually I will
|
2022-06-13 02:41:05 +00:00
|
|
|
produce some basic docs for making use of the exported functions, and will hopefully be able to provide a
|
|
|
|
download for a precompiled library. I'm still unsure if the source code will ever be made available however
|
2023-02-17 09:22:27 +00:00
|
|
|
because it's a <em>very</em> true to the original reproduction, potentially problematically so!
|
|
|
|
</p>
|
2022-06-13 02:41:05 +00:00
|
|
|
<p>If rather than implementing your own pcp you wish to use <em>the</em> libpcp, watch this space.</p>
|
|
|
|
</details>
|
|
|
|
|
2023-02-17 09:22:27 +00:00
|
|
|
{% endblock %}
|