The simplest message protocol.
This is a protocol to organize your network communication, rather than serialize/unserialize message payload.
Currently, the most popular message protocol in embed devices is MQTT, but it is so complex
to handle QoS
. This protocol removed this feature, just use for send data, the QoS
should be managed by the
upper application.
The version contains two fields: MAJOR
and MINOR
. Each one field ranges from 0
to 15
, 0
to 0xF
in hex.
And could be print as string in format MAJOR.MINOR
.
The version is 0.1
currently, in drafting.
A message includes any fields of the follow, and some fields is required, others is optional. If any field of the following headers exists, MUST be arranged in the following order.
Required, the message kind, the values means as follow:
0
:Ping Message
1
:Request Message
2
:Notify Message
3
:Response Message
Required, this means the payload encoding type, just like Content-Type
in HTTP protocol, but this is a flag to
represent it. This field means maybe different in different sense, according to the two peer how to comprehend it.
But there is some reserved values as follow:
0
: Reserved, means without payload1
: Protocol Buffers, see Protocol Buffers2
: JSON, see JSON3
: MessagePack, see MessagePack4
: BSON, see BSON5
: Raw, means the payload is a raw binary bytes or string
Optional, the message id, from 0x0000
to 0xFFFF
, this is determined by the KIND
field.
Optional, the request action id, from 0x00000000
to 0xFFFFFFFF
, this is use for application to distinguish the
request resource.
Actions from 0x00
to 0xFF
is reserved, some of those is using now, and list as follow:
0x00
: CheckVersion, this is use for check the protocol version.
Optional, the response status code, from 0x00
to 0xFF
, this is use for response message, the codes from
0x00
to 0x7F
is reserved for internal usages. And the codes from 0x80
to 0xFF
is user defined. The reserved
code list as follow: (just change the code value from http)
0x00
: Ok, 2000x10
: MovedPermanently, 3010x11
: Found, 3020x12
: NotModified, 3040x20
: BadRequest, 4000x21
: Unauthorized, 4010x22
: PaymentRequired, 4020x23
: Forbidden, 4030x24
: NotFound, 4040x25
: RequestTimeout, 4080x26
: RequestEntityTooLarge, 4130x27
: TooManyRequests, 4290x30
: InternalServerError, 5000x31
: NotImplemented, 5010x32
: BadGateway, 5020x33
: ServiceUnavailable, 5030x34
: GatewayTimeout, 5040x35
: VersionNotSupported, 505
Optional, the payload size, from 0x00000000
to 0xFFFFFFFF
, this is determined by the network protocol
environment, so this is a configure option when parse/serialize a message. If a message without payload (ENCODING
is 0
), this field SHOULD NOT exists in any protocol.
Optional, the size is determined by ENCODING
field, if it is 0
, this field should not exists, else should
be marshaled by the codec bind to the ENCODING
type.
This is a heartbeat packet. This message should not be replied. Each peer should keep a timer to send this packet, if a peer does not receive this message in time, MUST close the connection immediately.
This message MUST NOT contains any optional fields, that means all the fixed fields value is 0
.
This means a request from a peer, the other peer should send response to the peer in time, if the response is timeout,
the peer should emit a timeout error to application. A peer received this message must send a Response Message
to
the other peer, and the ID
is same to the message.
This message MAYBE contains PAYLOAD
and PS
, MUST NOT contains STATUS
, MUST contains ID
and ACTION
.
This means a notify message from a peer, the other peer should not response to the peer.
This message MAYBE contains PAYLOAD
and PS
, MUST NOT contains ID
and STATUS
, MUST contains ACTION
.
This means a response message for a Request Message
, the ID
must same to the request message.
This message MAYBE contains PAYLOAD
and PS
, MUST NOT contains ACTION
, MUST contains ID
and STATUS
.
In most cases, the message protocol is use for embed device, the environment could handle bytes easily, and serialize payload with binary protocol just like Protocol Buffers, MessagePack is fast. The protocol use binary struct directly.
NOTE:
- all multi-bytes flags/value use
BE
format.
The entire message structure as follow:
| 0 ... 7 | 8 ... 15 | 16 ... 23 | 24 ... 31 |
| FixedHeader | ID | ACTION |
| ACTION | STATUS |
| PS |
| PAYLOAD ... |
The first 1 byte is for fixed header, it exists in any kind of message, and other field is determined by the fixed header. If the field should not exists, it will not exist, and the follow-up fields will move forward.
The fixed header structure as follow:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| KIND | ENCODING | 0 | 0 | 0 |
The last one bit is reserved because it is useless currently.
Sometimes, specially, in browser, the environment does not support manipulate bytes directly, or the performance is poor. So use string is better rather than binary(in this case is Uint8Array). So, this is a special case to handle it.
The case includes the following features could use this:
- The network protocol could distinguish binary/string message directly.
- The environment could handle UTF-8 encoded string.
If the message is a binary bytes, is same to upon, else the message should be:
All fields and message types is same to upon, and we just need to change the serialize result.
All fields is joined by string |
, that means a full message format is follow:
KIND(1)|ENCODING(1)|ID?(1-5)|ACTION?(1-10)|STATUS?(1-3)|PS?(1-10)|PAYLOAD?(...)
For a specified kind of message, some fields maybe not exists, and that field will not exist in the text. For example,
for a Request Message
, without PAYPLOAD
and PS
, the message should be as follow:
1|0|ID|ACTION
Specially, for a Ping Message
all field is 0
, So, a Ping Message
should be serialized as a 1 byte string '0'
.
0
As the protocol definitions. If a message is texture, the first byte must be one of the chars
'0'
, '1'
, '2'
, '3'
, which means 0x30
, 0x31
, 0x32
, 0x33
in hex. And if a message is binary, the
first byte must be one of the following case:
- be
0x00
, this is a ping message - greater than
0b01000000
, the first 2 bits is the flag ofKIND
, if isPing Message
, the entire byte MUST be0x00
, else the first 2 bits MUST NOT be0x00
, so the value must greater than0b01000000
,0x40
in hex.
So, the first byte of one message is enough to distinguish texture and binary message.
Some actions is reserved for protocol internal usage.
When the connection established, the client must send a Request Message
with Check Version
action to check version,
the payload of the request is the version list that the client could handle. The server must response a Ok
message to the client if it could handle one of the versions sent by client when the server receive the request. If not,
the server must response a VersionNotSupported
message to the client and then close the connection.
The Check Version Request Message
and the response's ENCODING
MUST be Raw
. The payload is concat the version
list directly.
If the message is binary, a version should cost 1 byte, the first 4 bits is the MAJOR
field and the last 4 bits is
the MINOR
version, both range from 0x0
to 0xF
.
If the message is texture, a version should cost 2 bytes, the first byte is the MAJOR
field and the last byte is the
MINOR
version, both range from '0'
to 'F'
, case insensitive.
MIT