Packet and Message Spec

Each module in an OSAP System has a runtime (normally corresponding to the root osap. object), a list of links (data transport modules), and a list of ports (software interfaces).


Ports and Links each have a unique index within their runtime, and we make routes between modules by enumerating ‘hops’ across links. Each hop is an instruction, and packet headers contain lists of these instructions as byte-codes.

Within a system, there is one unique route between any port to any other port.


Using index-based routes at the functional level makes OSAP fast and small, but enumerating lists of numbers is semantically meaningless for most system programmers.

So, OSAP includes a naming scheme and resolves human-readable strings to machine-readable routes during operation. These names (and routes) are all discoverable.

Each module has a runtime-editable, nonvolatile name that is meant to be unique to that instance. They also have a typename and version number, which are immutable during runtime.

Ports and Links in each module also each have a name (unique throughout the module), and a typename.

This means that any port or link is also addressable by a unique set of semantically meaningful strings, and systems assembly typically resolves to calls like osap.send(payload, "moduleName", "portName")

Overall Packet Structure

The packet’s first 5 bytes encode a pointer (to the currently relevant instruction), as well as fields for the packet’s Time To Live (TTL) and Maximum Segment Size (MSS) that are required for packet prioritization / timeouts and for chunking replies.

The pointer is arranged such that packet[packet[0]] resolves to the currently-relevant packet instruction.

I am also reserving the very first bit in cases where we want to modify this structure, perhaps to shrink or enlarge the TTL and MSS fields to save packet space, or operate on much larger modules.

B0 [0]B0 [1:7]B1B2B3B4B5 ...... BN
RPTRTTL: 0-65535 MicrosecondsMSS: 0-65535 Bytes... Instructions... Payload

Packet Instructions

Packet headers encode instructions, which are operated on by the distributed system as the packet traverses through modules.

01234567 01234567 01234567
System Message: OSAP Internal Messages for Discovery, etc.
SMSG (0)RMSG KEY (0-31)|
Point Forward: Send the packet along a simple link.
LFWD (1)RLink Index (0-31)|
Bus Forward: Send the packet along a bus link.
BFWD (2)R Link Index (0-31)Rx Addr (0-255)|
Port Datagram: The packet is a datagram for a port in this module. Source port provided for replies.
(PKEY_DGRM << 6 | source >> 6) (source << 2 | destination >> 8) (destination & 255)
DGRM (3)RR Source Index (0-1023)Destination Index (0-1023)

System Messages

We’d like to have a minimum of these messages in order to return a full map of the transport layer, while also keeping maximum messages sizes under 16 bytes each.

The MSG ID is a tag used across system messages to disambiguate responses to requests, a they are collected at the request issuer. Basically a callback tag, they let us issue up to 255 messages to an individual module at a time.

Runtime Info Request / Response

This is the initial poke into a module, getting link, bus and port counts, as well as the module’s name, type and version.

The Trace Session ID is a stateful tag for graph traversals. When a module recieves an RTINFO_REQ from another module, it stores the transmitted session ID and replies with the most-recently stored session ID. This is required in order for graph traversals to function when there are loops in the system’s connectivity; it allows the tracer to identify when it is starting to recurse back through sections of the graph that it has already discovered.

B0[0:1] B0[2] B0[3:7] B1 B2, B3, B4, B5
B0[0:1] B0[2] B0[3:7] B1 B2, B3, B4, B5 B6 B7 B8 B9 B10, B11 B12[0:2] B12[3:7] B13[0:5] B13[6:7], B14[0:7]
SMSG R RTINFO_RES (1) MSG ID Prior Trace Session ID Runtime Type OSAP Ver. Major OSAP Ver. Mid OSAP Ver. Minor Instruction of Arrival R Point Link Count (0-31) Bus Link Count (0-31) Port Count (0-1023)

Module Type Get

B0[0:1] B0[2] B0[3:7] B1
B0[0:1] B0[2] B0[3:7] B1 B2 B3 B4 B5[0:1] B5[2:7] B6 ... BN
SMSG R MTYPEGET_RES (3) MSG ID Module Ver. Major Module Ver. Mid Module Ver. Minor R Type Name Len (0-63) Type Name

Module Name Get

B0[0:1] B0[2] B0[3:7] B1
B0[0:1] B0[2] B0[3:7] B1 B2[0:1] B2[2:7] B3 ... BN
SMSGR MNAMEGET_RES (5) MSG ID R - Module Name Len (0-63) Module Name

Module Name Set

B0[0:1] B0[2] B0[3:7] B1 B2[0:1] B2[2:7] B3 ... BN
SMSG R MNAMESET_REQ (6) MSG ID R Module Name Len (0-63) Module Name
B0[0:1] B0[2] B0[3:7] B1 B2

Once we have a port count, we can scan each individual for its state (open/closed/opening/closing), typename, and a proper name (very similar to ports).

‘typelen = 0’ is the null point-link !

B0[0:1] B0[2] B0[3:7] B1 B2[0:2] B2[3:7]
B0[0:1] B0[2] B0[3:7] B1 B2[0] B2[1:2] B2[3:7] B3 ... BN BN+1[0:1] BN+1[2:7] ... BM
SMSG R LINKINFO_RES (13) MSG ID R State (0-3) Type Len (0-32) Type Name R Name Len (0-64) Name

Port Info Collection

  • ‘typelen = 0’ is the null port… ?
B0[0:1] B0[2] B0[3:7] B1 B2[0:5] B2[6:7], B3[0:7]
SMSG R PORTINFO_REQ (12) MSG ID R Index (0-1023)
B0[0:1] B0[2] B0[3:7] B1 B2[0:2] B2[3:7] B3 ... BN BN+1[0:1] BN+1[2:7] ... BM
SMSG R PORTINFO_RES (13) MSG ID R Type Len (0-32) Type Name R Name Len (0-64) Name

// get bus-link info 
  • TBD: we need to get a state mask (~ 33 bytes, each bit 0-255 on/off) and then get more detail of
  • we also want to get the type and name…
  • maybe three msgs for busses: names, states (overview), states (detail)


  • it would be rad to have hover-over for each field w/ alt description, etc, for i.e. ‘MSS’ or ‘TTL’ … lil in-context explainers