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