Messages

Messages are the central data structures exposed by a protocol. They define a data layout and are used for runtime serialization and deserialization of data.

A message consists of an XML element with its sole child element being a record holding the data fields along with their metadata.

A DML message may be defined like this:

<MSG_PING>
  <RECORD>
    <!-- Message metadata -->
    <_MsgName TYPE="STR" NOXFER="TRUE">MSG_PING</_MsgName>
    <_MsgType TYPE="UBYT" NOXFER="TRUE">1</_MsgType>
    <_MsgDescription TYPE="STR" NOXFER="TRUE">PING request.</_MsgDescription>
    <_MsgHandler TYPE="STR" NOXFER="TRUE">MSG_Ping</_MsgHandler>
    <_MsgAccessLvl TYPE="UBYT" NOXFER="TRUE">0</_MsgAccessLvl>

    <!-- Data fields -->
    <Count TYPE="UINT"></Count>
  </RECORD>
</MSG_PING>

Records

Records only ever occur as XML elements named RECORD inside protocol information elements and messages.

They group various fields together.

Fields

Fields are used to represent the data layout of a DML message structure or important metadata for both, protocols and messages alike. They only ever occur inside record elements.

When used to describe metadata, fields always have a fixed value assigned to them. In most cases however, their values are undefined and will be filled with runtime object values.

Field attributes

Fields may carry specific properties indicated by key-value pairs of XML attributes. The following presents known attributes, their supported values, and how they influence the behavior of a field.

Types

The most common attribute is TYPE. It specifies the data type of fields using a string acronym:

NameTypeDescription
BYTint8Signed 8-bit integer
UBYTuint8Unsigned 8-bit integer
USHRTuint16Unsigned 16-bit integer in little-endian byteorder
INTint32Signed 32-bit integer in little-endian byteorder
UINTuint32Unsigned 32-bit integer in little-endian byteorder
STRuint8[]A length-prefixed string of arbitrary bytes (may be UTF-8)
WSTRuint16[]A length-prefixed string of UTF-16 code points in little-endian order
FLTfloatIEEE-754 32-bit floating point number in little-endian byteorder
DBLdoubleIEEE-754 64-bit floating point number in little-endian byteorder
GIDuint64Unsigned 64-bit integer in little-endian byteorder

Visibility

Every field may individually control whether it is visible as a serializable data field or not. This is accomplished by setting the NOXFER attribute to either "TRUE" or "FALSE".

NOXFER stands for "No Transfer" and is mostly used for metadata fields which carry fixed values. As per convention, such fields should always start with an underscore (_) in their name to highlight the hidden status.

Serialization

Serialization and deserialization of a message works by consecutively iterating through the fields in the order they were listed in the message specification, and encoding the value as defined by the type. Fields with the NOXFER attribute will be skipped.

Example

The message

<MSG_PERSON>
  <RECORD>
    <Name TYPE="STR">Edgar Allan Poe</Name>
    <Age TYPE="UBYT">40</Age>
  </RECORD>
</MSG_PERSON>

serializes to

[
    # String length prefix (15)
    0x0f, 0x00,
    # String bytes without null terminator (Edgar Allan Poe)
    0x45, 0x64, 0x67, 0x61, 0x72, 0x20, 0x41, 0x6c, 0x6c, 0x61, 0x6e, 0x20, 0x50, 0x6f, 0x65,
    # Age byte (40)
    0x28
]

Metadata

The records of messages may have a set of hidden fields assigned to them which solely describe metadata required for runtime handling and querying of individual messages.

Unlike the protocol information however, these fields must all be marked as NOXFER.

Below is a list of fields and their meaning. Some of them are discussed in greater detail in subsections of this paragraph.

NameTypeOptionalDescription
_MsgNameSTRtrueThe name of the message; Overrides the XML message tag
_MsgOrderUBYTtrueThe order value
_MsgDescriptionSTRtrueShort description of the message and its purpose
_MsgHandlerSTRfalseThe handler callback to process this message when received
_MsgAccessLvlUBYTtrueThe access level for the message

Order number

Every message has its own index assigned to it that is unique within a protocol - the order value. Order values usually start at 1 and are used in combination with the unique service ID of the protocol to address a specific message when several protocols are available at once.

As the value is represented as an unsigned 8-bit integer, the amount of messages per protocol is limited to 255 as a result of that.

Order values may either be explicitly specified using the _MsgOrder field or left away for every message within the protocol. In case of the latter, the implementation automatically assigns order values in ascending order by sorting message names (name from xml tag; NOT _MsgName) alphabetically. Mixing both approaches up may result in collisions!

Access level

The access level defines the minimum value that must be held by a session in order to be allowed to process the message.

For the scope of the system, this trait is fairly unimportant, but it plays a great role in handling network sessions and is further explained there.