Protocol specification

RPC specification is simple enough, and made very close to jsonrpc

MessagePack RPC Spec

Request

Simple request. Ask server to call some function and return results in blocking fashion.

Packet scheme

+---+-------+--------+--------+
| 0 | msgid | method | params |
+---+-------+--------+--------+

Example

Call multiply function with one param 2.

>>> msgpack.loads('\x94\x00\x0c\xa8multiply\x91\x02')
(0, 12, 'multiply', (2,))

Reply

Simple reply. Server sends reply after call was completed.

Packet scheme

+---+-------+-------+--------+
| 1 | msgid | error | result |
+---+-------+-------+--------+

Example

This is reply for request example above

>>> msgpack.loads('\x94\x01\x0c\xc0\x04')
(1, 12, None, 4)

Notification

Variant of simple request, for which client dont want to wait result. This way client sends notification, may disconnect immidiately, while servers run requested function in asynchronous way. But client will not be able to receive results (server dont even try to send them).

Packet scheme

+---+--------+--------+
| 2 | method | params |
+---+--------+--------+

Example

>>> msgpack.loads('\x93\x02\xa8shutdown\x90')
(2, 'shutdown', ())

joint Spec

All MessagePack RPC above is supported (of course...). But in addition to original specification joint has its own extensions.

Request

Extended request:

  1. params can be either list or dictionary or both and they are not required
  2. client may ask server to run meth in separate subprocess
  3. client may ask server to run meth with async flow

Packet scheme

+------------+---------+-------+--------+---------+-----------+
| offset + 0 | req_opt | msgid | method | params? | kwparams? |
+------------+---------+-------+--------+---------+-----------+

Options (req_opt)

REQUEST_OPT_ASYNC_FLOW
Value :1
REQUEST_OPT_RUN_SUBPROCESS
Value :2

Request throw

Packet scheme

+------------+-------+------+
| offset + 0 | msgid | data |
+------------+-------+------+

Reply

Packet scheme

+------------+---------+-------+--------+
| offset + 1 | rep_opt | msgid | result |
+------------+---------+-------+--------+

Options (rep_opt)

REPLY_ERROR
Value :1
REPLY_OPT_HAS_MORE
Value :2

If remote function returned generator, there will be multiple reply packets with final reply with result set to null. Once client received yield packet it can throw something back using Request throw packet.

Pings

Pings normally should be asynchronous. Main idea is simple: in classic rpc it is too hard to detect if connection “stucks”. You call some meth, but you dont really now how much time it will be executed.

Normal scenario:

--> call something
<-- ok, calling
<-- (after some time) here is a result

But what if connection hangs after meth was called, but before result was made:

--> call something
<-- ok, calling
(connection freezes)

Right now we dont know how much to wait. Because we cant detect what’s happening on server side. With pings this can be done easily:

--> call something
<-- ok, calling
(after ping interval)
--> ping
<-- pong
(after ping interval, meanwhile connection freezes)
--> ping
(wait on client side for pong for hardcoded ping timeout and abort)

Pings always issued by client side. Pongs – by server side.

Packet scheme (ping)

+------------+
| offset + 3 |
+------------+

Packet scheme (pong)

+------------+
| offset + 4 |
+------------+