Metacom is a top-level application protocol for RPC (remote procedure call) and large binary objects transfer. Metacom requires frame-based transport, for example websocket. TCP and TLS can be used as underlying transport but additional converting layer (described below) is needed to have frame-based transport instead of stream-based one. Metacom can support multiple serialization formats like JSON (by default) and MDSF (JSON5 implementation), V8 serialization API, BSON, etc. Metacom is a simplification and modernization of JSTP protocol.
There are following packet types: call
, callback
, event
, stream
, ping
.
Call format:
{
type: "call",
id: number, // we need call id to match result (metacom callback packet)
method: string, // method name format: unit/name or unit.version/name, example: "chat.5/send"
args: object, // we use named arguments to be able mark them optional
meta: object, // field for optional passthrough metadata
}
Callback format:
{
type: "callback",
id: number, // call id
result: any, // any data (object, array or a single value)
error: { "code": number, "message": string },
meta: object, // field for optional passthrough metadata
}
Examples:
{"type":"call","id":110,"method":"auth/signIn","args":{"login":"marcus","password":"marcus"}}
{"type":"callback","id":110,"result":{"token":"2bSpjzG8lTSHaqihGQCgrldypyFAsyme"}}
Format:
{
type: "event", // events have no packet id, unlike call packets and events in metacom version 2
name: string, // event name in format: unit/name, example: "chat/message"
data: object, // attached data
meta: object, // field for optional passthrough metadata
}
Example:
{"type":"event","name":"unit/message","data":{"from":"marcus","message":"Hello!"}}
Stream initialization:
{
type: "stream",
dest: 'server' | 'client',
id: number,
name: string,
size: number,
}
Stream chunk:
{
type: "stream",
dest: 'server' | 'client',
id: number,
} // Next frame: `Buffer`
Stream finalization:
{
type: "stream",
dest: 'server' | 'client',
id: number,
status: "end",
}
Stream termination:
{
type: "stream",
dest: 'server' | 'client',
id: number,
status: "terminate",
}
Client may periodically generate ping packets {}
(empty objects, without
fields and id) to test connection. Server should also answer with empty object
{}
.