Protocol - element-ts/lithium GitHub Wiki
When a client starts a new connection to a server via the LiSocket.init()
static async method, it generates a new
socket using the ws package. It then waits to get its id
from the server using an
internal command.
Once an id
is generated by the server, and the server has processed the new connection, the init()
method on
LiSocket
sets its id
and resolves the promise. This is why the method is async.
When a command is invoked by a socket, it creates an LiMessage
object which looks like below:
{
timestamp: Date.now(),
command: "the-command-name",
param: 42,
id: "an-id-created",
peerToPeer: false
}
It sets the timestamp to the current time. The command and param are self-explanatory. For id
, the LiMessageManager
instance attached to the LiBaseSocket
generates a new non-colliding identifier and adds the new message's handler
to an internal map.
The message object is stringified by @elijahjcobb/better-json. All this
package does is stringify it but correctly handles the conversion for Buffer
objects. The string is then converted
into a Buffer
and sent through the socket. On the other side, the corresponding LiBaseSocket
parses the binary data
and gets it back to an LiMesage
.
The socket then checks the types of the message and finds the handler provided by the implement
method in the socket's
LiCommandRegistry
instance. It runs the handler. If the handler throws an error the socket will catch it. Then it
packages up the response of the handler whether it be a correct response or error and creates a new LiMessage
where
the timestamp, is the original message's timestamp, the command, is either "return"
or "error"
. The param is the
return value or error, the id is the original message's id, and peerToPeer is set to false unless it is a peer-to-peer
command.