3.5 Message Framing

MSIP reuses the header layout of §2.6 with its own magic. Every message begins with a 12-byte header:

OffsetSizeFieldValue
04magicMSIP (4d 53 49 50)
42version1
62msg_typeSee §3.A
84total_lenHeader plus body, in bytes

The rules of §2.6 apply unchanged to the magic (checked on every message; wrong magic is an immediate whole-connection failure), to the version (an unimplemented version MUST be refused; here, by closing the connection, optionally after an Error where one can still be encoded), and to total_len (self-delimiting; a decoder MUST reject a declaration exceeding the limit without reading the body, and one smaller than the header).

The high bit of msg_type marks a message sent by the daemon; surface messages have it clear. As in §2.6, this is a readability property — a peer MUST validate the type it received against what it expected, not merely against the direction bit.

A message MUST NOT exceed 1 MiB in total. The limit is larger than the logon channel's because log elements legitimately carry bulk; it is a limit all the same.

3.5.2 Body #

The body is one JSON object, UTF-8 encoded, as defined by RFC 8259. Which object each message type carries is specified in §3.6 to §3.11 and tabulated in §3.A. The message type lives in the header only; the body does not repeat it.

A decoder MUST reject a body that is not valid UTF-8, not valid JSON, or not an object, as a protocol error (§3.11).

3.5.3 Extensibility #

The JSON body extends by different rules than the binary codec, and they are binding on anyone revising this chapter:

  • A decoder MUST ignore an object key it does not know. New fields are added as new keys, and MUST be optional with a safe default, because older peers will not send them and will not read them.
  • An absent optional field and a field carrying its documented default MUST NOT be distinguished.
  • A peer MUST treat an unknown value of an enumerated field — Refused.reason, Error.code, End.outcome — as a protocol error. Adding a value to an enumeration is a breaking change and requires a version bump.

Element types and element state are the deliberate exception, as supported_credential_types is to Logon (§2.6): the set a surface renders is a statement of capability negotiated at HELLO, a daemon MUST NOT send an element type the surface did not declare, and a type's state keys are defined by the element type (§3.B), not by the message format. Adding an element type is therefore not a version bump — an old surface simply does not declare it.

Edit this page