fast_rpc/
lib.rs

1// Copyright 2019 Joyent, Inc.
2
3//! Fast: A simple RPC protcol used by Joyent products
4//!
5//! Fast is a simple RPC protocol used in
6//! Joyent's[Triton](http://github.com/joyent/triton) and
7//! [Manta](https://github.com/joyent/manta) systems, particularly in the
8//! [Moray](https://github.com/joyent/moray) and
9//! [Boray](https://github.com/joyent/boray) components.
10//!
11//! Protocol overview
12//!
13//! The Fast protocol is intended for use with TCP.  Typically, a Fast server
14//! listens for TCP connections on a well-known port, and Fast clients connect
15//! to the server to make RPC requests.  Clients can make multiple connections
16//! to the server, but each connection represents a logically separate
17//! client. Communication between client and server consist of discrete
18//! _messages_ sent over the TCP connection.
19//!
20//! Fast protocol messages have the following structure:
21//!
22//! <img src="../../../docs/fastpacket.svg" width="100%" height="100%">
23//!
24//! * VERSION   1-byte integer.  The only supported value is "1".
25//!
26//! * TYPE      1-byte integer.  The only supported value is TYPE_JSON (0x1),
27//!           indicating that the data payload is an encoded JSON object.
28//!
29//! * STATUS    1-byte integer.  The only supported values are:
30//!
31//!     * STATUS_DATA  0x1  indicates a "data" message
32//!
33//!     * STATUS_END   0x2  indicates an "end" message
34//!
35//!     * STATUS_ERROR 0x3  indicates an "error" message
36//!
37//! * MSGID0...MSGID3    4-byte big-endian unsigned integer, a unique identifier
38//!                    for this message.
39//!
40//! * CRC0...CRC3        4-byte big-endian unsigned integer representing the CRC16
41//!                     value of the data payload
42//!
43//! * DLEN0...DLEN4      4-byte big-endian unsigned integer representing the number
44//!                    of bytes of data payload that follow
45//!
46//! * DATA0...DATAN      Data payload.  This is a JSON-encoded object (for TYPE =
47//!                    TYPE_JSON).  The encoding length in bytes is given by the
48//!                    DLEN0...DLEN4 bytes.
49//!
50//! ### Status
51//!
52//! There are three allowed values for `status`:
53//!
54//! |Status value | Status name | Description |
55//! |------------ | ----------- | ----------- |
56//! | `0x1`        | `DATA`      | From clients, indicates an RPC request.  From servers, indicates one of many values emitted by an RPC call.|
57//! | `0x2`        | `END`       | Indicates the successful completion of an RPC call.  Only sent by servers. |
58//! | `0x3`        | `ERROR`     | Indicates the failed completion of an RPC call.  Only sent by servers. |
59//!
60//! ### Message IDs
61//!
62//! Each Fast message has a message id, which is scoped to the Fast
63//! connection.  These are allocated sequentially from a circular 31-bit space.
64//!
65//! ### Data payload
66//!
67//! For all messages, the `data` field contains properties:
68//!
69//! | Field    | Type              | Purpose |
70//! | -------- | ----------------- | ------- |
71//! | `m`      | object            | describes the RPC method being invoked |
72//! | `m.name` | string            | name of the RPC method being invoked |
73//! | `m.uts`  | number (optional) | timestamp of message creation, in microseconds since the Unix epoch |
74//! | `d`      | object or array   | varies by message status |
75//!
76//! ### Messaging Scenarios
77//!
78//! Essentially, there are only four messaging scenarios with Fast:
79//!
80//! **Client initiates an RPC request.** The client allocates a new message
81//! identifier and sends a `DATA` message with `data.m.name` set to the name of
82//! the RPC method it wants to invoke.  Arguments are specified by the array
83//! `data.d`. Clients may issue concurrent requests over a single TCP
84//! connection, provided they do not re-use a message identifier for separate
85//! requests.
86//!
87//! **Server sends data from an RPC call.** RPC calls may emit an arbitrary
88//! number of values back to the client.  To emit these values, the server sends
89//! `DATA` messages with `data.d` set to an array of non-null values to be
90//! emitted.  All `DATA` messages for the same RPC request have the same message
91//! identifier that the client included in its original `DATA` message that
92//! initiated the RPC call.
93//!
94//! **Server completes an RPC call successfully.** When an RPC call completes
95//! successfully, the server sends an `END` event having the same message
96//! identifier as the one in the client's original `DATA` message that initiated
97//! the RPC call. This message can contain data as well, in which case it should
98//! be processed the same way as for a DATA message.
99//!
100//! **Server reports a failed RPC call.** Any time before an `END` message is
101//! generated for an RPC call, the server may send an `ERROR` message having the
102//! same message identifier as the one in the client's original `DATA` message
103//! that initiated the RPC call.
104//!
105//! By convention, the `m` fields (`m.name` and `m.uts`) are populated for all
106//! server messages, even though `m.name` is redundant.
107//!
108//! The RPC request begins when the client sends the initial `DATA` message.
109//! The RPC request is finished when the server sends either an `ERROR` or `END`
110//! message for that request.  In summary, the client only ever sends one
111//! message for each request.  The server may send any number of `DATA` messages
112//! and exactly one `END` or `ERROR` message.
113
114#![allow(missing_docs)]
115
116pub mod client;
117pub mod protocol;
118pub mod server;