3.4. Node Commands

A command is the unit of communication using Verse. Commands are sent between client and host and express either global actions affecting the session as a whole, or address individual nodes directly.

The set of available commands is strictly defined in this specification, and Verse-compliant applications cannot go outside it. This is because a goal with Verse is interoperability, and the set of commands needs to be shared by all applications for this to be achieved. There are about 60 unique commands defined in this specification.

3.4.1. Structure

The structure of a Verse network command is simple: a command is a finite sequence of bits. This sequence consists of individual fields of varying length. A field is typically a value in one of the supported network data formats and encoded according to the encoding standard. The first field has a fixed length of 8 bits, and always holds an integer value that identifies the command. This field is called the command ID (or command byte) and completely determines the format of the subsequent bits. The following bytes make up the command's parameters, which are very much analogous to parameters in ordinary function calls.

The value of the initial command byte completely determines the exact format of the following bits, and also how many bits are present. The size of a command need not be constant, however; there are both variable-length single parameters (zero-terminated character strings) and parameters whose presence is determined by the value of previous parameters in the same command.

3.4.1.1. System vs. Node Commands

There are two major categories of commands: system commands, and node commands. The defining difference here is that system commands are not not sent to any specific node, they alter the session as a whole. Node commands, on the other hand, are always sent to exactly one node. With this difference in mind, we can present the following two schematic views of command structure:

Table 3-2. A System Command

Field:IDparameters
Width:8variable

Table 3-3. A Node Command

Field:IDNode IDparameters
Width:832variable

 

As can be seen, node commands differ from system commands by always including a 32-bit ID of the target node as the first field following the command ID.

3.4.1.2. Addressing

Many commands need to uniquely specify what data it reads or writes. This is done by concatenating a sequence of fields in the encoded command, to form the address. For system commands, the command byte itself is sometimes enough, and no further address fields are defined. For node commands, the address is extended to always include the node ID field, and often further fields that address parts of the node.

Example 3-5. g_vertex_set_xyz_real32 Addressing

As an example, consider setting the (X,Y,Z) position of a geometry node base layer vertex. One command that does this is g_vertex_set_xyz_real32, which has a command ID value of 50. This command requires three pieces of information that together identify the vertex whose position is to be set: the node ID of the target node, the layer ID of the layer holding the vertex, and finally the vertex ID that is the index of the vertex inside the layer. These three values together make up the address part of the command.

In this case, we end up with a final address of (node ID, layer ID, vertex ID). Since the node ID is always 32 bits, and the layer and vertex IDs are 16 and 32 respectively, the address size is 32 + 16 + 32 = 80 bits.

3.4.1.3. Content

The rest of the parameters for a command make up the actual data payload, and little can be said about it in general; the specific format is very much up to each command.

Example 3-6. g_vertex_set_xyz_real32 Content

To continue from the previous example, the content used to set a vertex with 32-bit precision is simply three real32 values, named x, y and z respectively. These add 3 * 32 = 96 bits to the command's parameter block, bringing the total size of the command up to 8 + (32 + 16 + 32) + (3 * 32) = 184 bits, or 23 bytes.

3.4.2. Command Symmetry

The way commands are actually used to convey information is interesting, and needs to be described explicitly since it is perhaps not totally intuitive to everyone.

Verse node commands are very much like remote procedure calls; one end of a point-to-point network connection can tell the other end to do something, like create a node. What makes them interesting is the way in which the result of the operation is made known to the sender: typically, this is done by sending the same command in the other direction, sometimes with a few values filled in that were left blank originally.

This means that if a client sends a command to a host, asking it to e.g. move a vertex to a new position in 3D space (using the g_vertex_set_xyz_real32 command), the following will happen: [1]

  1. The Verse network layer on the host receives the command, and notifies [2] the host application.

  2. The host code validates the command, making sure it addresses a valid vertex, and that the sending client has the right to execute the command. If it doesn't, processing ends here.

  3. The host executes the command, typically by updating the state of the vertex layer with the new position.

  4. The change must be distributed to all subscribers, probably also including the client that originally sent the change. This is done by having the host construct a suitable command (for this example, this would be the exact same command, i.e. a g_vertex_set_xyz_real32), and sending it out to all known subscribers.

  5. The originating client's Verse network layer receives the update command, decodes it, and notifies the application layer.

The point here is that the same sequence of bits (the command) is used both as a request from a client to a host, to "please set this object to this value" and as an authoritative message in the other direction, where the meaning is more along the lines of "be advised, this object now has this value". The distinction is subtle, but worth knowing about.

The above example is accurate, but only covers the case where there is a one-to-one correspondence between the command received by the host and the command emitted by it in response to executing the request. Many commands have a one-to-many relation instead; a client sends a single command, and the server responds with a burst of many commands in return. This is common when requesting for a subscription to some data, for example; the request is a single command, but the description of the data, which needs to be send to the new subscriber, often requires several commands. In such cases, of course, there is no 1:1 relationship between what gets sent by the client and what gets sent in response by the server. However, the individual commands used to describe the data are still the same in both directions.

Notes

[1]

This example does not include sufficient detail to describe what happens if one or more commands are lost in transit, which is always a possibility. But since packet-loss should be handled in a well-defined manner, it can be ignored here.

[2]

In the standard API defined in this document, this notification is through the invocation of a callback function.