RemoteFile v1.1¶
RemoteFile is a binary, message-based protocol used to synchronize virtual memory regions across a point-to-point communication link (such as a TCP socket, UNIX domain socket, or shared memory). It acts as the application transport layer of an active APX session.
Note
For an architectural overview, memory model rationale, and high-level diagrams, see The RemoteFile Protocol in Internal Design.
Overview of RemoteFile v1.1¶
RemoteFile v1.1 extends the baseline RemoteFile v1.0 protocol with enhanced handshake negotiation, explicit error signaling, server runtime monitoring, and cryptographic authentication:
Protocol Greeting & Handshake: Employs protocol identifier
RMFP/1.1\nwith explicit framing size (Message-Size) and client role (Connection-Type) declarations.Connection Identifier Assignment (
RMF_CMD_ACCEPT_HEADER): Replaces the basic acknowledgement response with an explicit command delivering a server-assigned 32-bit connection ID.Rich Error Reporting (
RMF_CMD_NACK): Expands negative acknowledgement from an empty opcode into a structured command containing a 32-bit error code and an optional node name string.Cryptographic File Authentication (
RMF_CMD_PUBLISH_SIGNED_FILE): Introduces file publication with attached digital signatures (ECDSA P-256), enabling zero-trust authentication of node interfaces.Runtime Connection Monitoring (
RMF_CMD_CONNECTION_CREATE,RMF_CMD_CONNECTION_REVOKE): Allows monitoring extensions to receive real-time connection lifecycle events.Expanded File Types: Formalizes support for dynamic files with 8-, 16-, and 32-bit length headers, device files, and streaming FIFO queues.
Memory Model & Addressing¶
RemoteFile models communication as bidirectional memory synchronization. Each peer maintains two 1GB (\(2^{30}\) bytes) virtual memory spaces:
Memory Map |
Address Range |
Description |
|---|---|---|
Local Map |
|
Mapped files owned and published by the local endpoint (1,073,740,800 bytes). |
Remote Map |
|
Mirrored files published by the remote peer, including the control area (1,073,741,824 bytes). |
The last 1KB (1024 bytes) of the remote address space (0x3FFFFC00 – 0x3FFFFFFF) is reserved for the Control Area, which is used to exchange commands such as file announcements, open/close requests, and connection lifecycle events.
Normative Addressing Rules¶
Rule 1 (Data Area Writes):
A memory write targeting an address below
0x3FFFFC00is illegal unless:
A file exists at that address range.
The file mapped at that address range has been previously opened by the remote peer.
Any write targeting an unopened file or exceeding file bounds must be ignored or treated as a protocol error.
Rule 2 (Control Area Writes):
A memory write targeting the Control Area (
0x3FFFFC00–0x3FFFFFFF) is valid if and only if:
The start address of the write is exactly
0x3FFFFC00.The total length of the write does not exceed 1024 bytes.
Rule 3 (Data Synchronization):
As long as an opened file remains active, any local modification to that file’s memory buffer must be immediately transmitted to the remote peer as a binary write command covering the modified byte range.
Wire Framing & Transport¶
RemoteFile is transport-agnostic and relies on point-to-point streaming connections. On stream-oriented transports (such as TCP or UNIX domain sockets), message framing must be provided by NumHeader.
For TCP connections, NumHeader32 is the recommended framing protocol.
Each transmitted message consists of:
Message Header: Length prefix encoded using NumHeader (1, 2, or 4 bytes).
Message Payload: The message body (greeting text or binary write payload).
Greeting Handshake¶
Upon establishing a physical connection, the client must send a Greeting Header as the very first message. The greeting is a multi-line text string (the only text-based message in the protocol) formatted similarly to an HTTP/MIME header.
Greeting Format¶
The first line must be the protocol identifier:
RMFP/1.1\nSubsequent lines contain optional key-value attributes formatted as
Key: Value\nThe greeting message must terminate with an additional newline (
\n).
Example Greeting:
RMFP/1.1
Message-Size: 32
Monitor Client Greeting Example:
RMFP/1.1
Message-Size: 32
Connection-Type: Monitor
Greeting Constraints¶
Maximum Length: The total length of the greeting message must not exceed 127 bytes. This ensures that the message length fits within the 1-byte short form of both NumHeader16 and NumHeader32.
Line Endings: Every line must end with a single UNIX newline (
\n,0x0A).
Greeting Attributes¶
Attribute |
Format |
Description |
|---|---|---|
|
|
Declares the NumHeader framing variant used for all subsequent messages from the client (default |
|
|
Legacy alias for |
|
|
Declares the connection role and subscription scope. Default is |
Connection Types:
Default: Standard node client that publishes and receives APX virtual files.Monitor: Administrative and monitoring client (used byapx_infoand monitoring extensions) that receives server state updates and connection lifecycle events.Event: Event-stream subscription client.
Handshake Sequence¶
In RemoteFile v1.1, the handshake protocol proceeds as follows:
Client Greeting: The client connects and sends its
RMFP/1.1text header.Server Acceptance:
The server validates the protocol version and parameters.
The server assigns a unique 32-bit
ConnectionIdto the session.The server transmits
RMF_CMD_ACCEPT_HEADER(CmdType = 20) containing the assignedConnectionIdto the client’s Control Area (0x3FFFFC00).(In contrast to RemoteFile v1.0, where the server replied with a bare 4-byte
RMF_CMD_ACK).
Session Active: After receiving the accept command, the client and server transition to active binary message exchange.
Binary Data Messages¶
After the greeting handshake completes, all communication consists exclusively of binary write messages.
Each write message payload contains:
Address Header: Encodes the target start address and fragmentation flags (2 or 4 bytes).
Data Buffer: The raw payload bytes to write into remote memory.
AddressHeader Formats¶
The AddressHeader comes in two forms depending on the target memory address:
Low Address Form (0 – 16,383): Occupies 2 bytes. Used for fast, compact updates to frequently changing data buffers.
+-------------------------------+-----------------------+
| Byte 0 | Byte 1 |
+-------+-------+---------------+-----------------------+
| Bit 7 | Bit 6 | Bits 5-0 | Bits 7-0 |
+-------+-------+---------------+-----------------------+
| 0 | M | Address MSB | Address LSB |
+-------+-------+---------------+-----------------------+
^ ^ \_______________________________________/
| | |
HIGH_BIT=0 | 14-bit Address (0 - 16,383)
|
MORE_BIT (0 = final packet, 1 = more packets follow)
Field |
Bits |
Value Range |
Description |
|---|---|---|---|
HIGH_BIT |
Byte 0, Bit 7 |
|
Specifies 2-byte Low Address form |
MORE_BIT |
Byte 0, Bit 6 |
|
Fragmentation flag ( |
Address |
Byte 0 (Bits 5–0) + Byte 1 (Bits 7–0) |
|
14-bit big-endian start address |
High Address Form (16,384 – 1,073,741,823): Occupies 4 bytes. Used for larger address ranges and the Control Area.
+-------------------------------+-----------+-----------+-----------+
| Byte 0 | Byte 1 | Byte 2 | Byte 3 |
+-------+-------+---------------+-----------+-----------+-----------+
| Bit 7 | Bit 6 | Bits 5-0 | Bits 7-0 | Bits 7-0 | Bits 7-0 |
+-------+-------+---------------+-----------+-----------+-----------+
| 1 | M | Address (30-bit) |
+-------+-------+---------------------------------------------------+
^ ^ \___________________________________________________/
| | |
HIGH_BIT=1 | 30-bit Address (0 - 1,073,741,823)
|
MORE_BIT (0 = final packet, 1 = more packets follow)
Field |
Bits |
Value Range |
Description |
|---|---|---|---|
HIGH_BIT |
Byte 0, Bit 7 |
|
Specifies 4-byte High Address form |
MORE_BIT |
Byte 0, Bit 6 |
|
Fragmentation flag ( |
Address |
Bytes 0–3 (Bits 29–0) |
|
30-bit big-endian start address |
AddressHeader Flags¶
HIGH_BIT(Bit 7 of Byte 0):0: Low address form (2-byte header, 14-bit address range0–16,383).1: High address form (4-byte header, 30-bit address range16,384–1,073,741,823).
MORE_BIT(Bit 6 of Byte 0):Used for message fragmentation. Set to
1if additional data packets follow for the same logical write operation.Set to
0on the final packet to signal the end of the write operation.Upper application layers must not be notified until the complete write operation has been received (
MORE_BIT = 0).
Framing Scenarios¶
Scenario |
NumHeader Format |
Address Format |
Use Case |
|---|---|---|---|
Short & Low |
Short (1 byte) |
Low (2 bytes) |
Writing 0–127 bytes to address 0–16,383 |
Long & Low |
Long (2 or 4 bytes) |
Low (2 bytes) |
Writing \(\ge 128\) bytes to address 0–16,383 |
Short & High |
Short (1 byte) |
High (4 bytes) |
Writing 0–127 bytes to address \(\ge 16,384\) |
Long & High |
Long (2 or 4 bytes) |
High (4 bytes) |
Writing \(\ge 128\) bytes to address \(\ge 16,384\) |
Byte Layout Examples¶
Short Length & Low Address (1-byte NumHeader + 2-byte AddressHeader):
Byte |
Protocol |
Meaning |
|---|---|---|
0 |
NumHeader16/32 |
Message Header (Length) |
1 |
RemoteFile |
Address Header (MSB) |
2 |
RemoteFile |
Address Header (LSB) |
3..N |
Payload |
Data Buffer |
Long Length & Low Address (4-byte NumHeader32 + 2-byte AddressHeader):
Byte |
Protocol |
Meaning |
|---|---|---|
0–3 |
NumHeader32 |
Message Header (31-bit Big-Endian length) |
4 |
RemoteFile |
Address Header (MSB) |
5 |
RemoteFile |
Address Header (LSB) |
6..N |
Payload |
Data Buffer |
Short Length & High Address (1-byte NumHeader + 4-byte AddressHeader):
Byte |
Protocol |
Meaning |
|---|---|---|
0 |
NumHeader16/32 |
Message Header (Length) |
1–4 |
RemoteFile |
Address Header (30-bit Big-Endian address, |
5..N |
Payload |
Data Buffer |
Long Length & High Address (4-byte NumHeader32 + 4-byte AddressHeader):
Byte |
Protocol |
Meaning |
|---|---|---|
0–3 |
NumHeader32 |
Message Header (31-bit Big-Endian length) |
4–7 |
RemoteFile |
Address Header (30-bit Big-Endian address, |
8..N |
Payload |
Data Buffer |
Control Commands¶
Control commands are issued by writing binary command structures to the Control Area at start address 0x3FFFFC00.
Command payload fields use Little-Endian (LE) byte order for multi-byte integers.
Command Identifiers (CmdType)¶
The first 4 bytes (U32LE) of any control command payload identify the command:
|
Value |
Version |
Description |
|---|---|---|---|
|
0 |
v1.0 |
Command Acknowledged |
|
1 |
v1.1 |
Negative Acknowledged (error code and node name) |
Reserved |
2 |
— |
Reserved |
|
3 |
v1.0 |
Publish / announce an unauthenticated file |
|
4 |
v1.0 |
Revoke / unmap a published file |
|
5 |
v1.0 |
Heartbeat Request |
|
6 |
v1.0 |
Heartbeat Response |
|
7 |
v1.0 |
Ping Request with timestamp |
|
8 |
v1.0 |
Ping Response with timestamp |
Reserved |
9 |
— |
Reserved |
|
10 |
v1.0 |
Open a published file |
|
11 |
v1.0 |
Close an opened file |
|
20 |
v1.1 |
Handshake Protocol Header Accepted with Connection ID |
|
21 |
v1.1 |
New connection created notification |
|
22 |
v1.1 |
Connection closed / revoked notification |
|
23 |
v1.1 |
Publish / announce a cryptographically signed file |
Handshake & Acknowledgment Commands¶
Header Accepted Command (RMF_CMD_ACCEPT_HEADER):
Sent by the server to a newly connected client upon validating its RMFP/1.1 greeting header. It confirms successful negotiation and informs the client of its unique 32-bit connection identifier.
Offset |
Field |
Type |
Value Range |
Description |
|---|---|---|---|---|
0 |
|
|
|
Command Identifier |
4 |
|
|
\(0\) – \(2^{32}-1\) |
Assigned 32-bit Connection ID |
Total size: 8 bytes.
Acknowledge Command (RMF_CMD_ACK):
Sent as a positive response to a command (and used in v1.0 for handshake confirmation).
Offset |
Field |
Type |
Value |
Description |
|---|---|---|---|---|
0 |
|
|
|
Command Identifier |
Total size: 4 bytes.
Error Handling Commands¶
Negative Acknowledge Command (RMF_CMD_NACK):
Sent to signal that an operation failed, an invalid command was received, or node verification failed. In RemoteFile v1.1, NACK conveys a 32-bit error code along with an optional null-terminated node name string identifying the failing component.
Offset |
Field |
Type |
Value Range |
Description |
|---|---|---|---|---|
0 |
|
|
|
Command Identifier |
4 |
|
|
See Error Codes below |
APX Error Code |
8 |
|
String |
ASCII |
Null-terminated name of the affected node (or |
Total size: \(8 + ext{strlen(NodeName)} + 1\) bytes (minimum 9 bytes).
Common APX Error Codes¶
Error Code |
Name |
Description |
|---|---|---|
|
|
Success / no error |
|
|
Invalid or malformed argument |
|
|
Syntax or grammar parsing error |
|
|
Command or feature unsupported by peer |
|
|
Node definition already registered |
|
|
File already mapped at requested address |
|
|
Referenced file not found |
|
|
Malformed or unsupported protocol greeting |
|
|
Node definition requires signature but none provided |
|
|
Cryptographic signature verification failed |
File Management Commands¶
FileInfo Command (RMF_CMD_FILE_INFO):
Announces that an unauthenticated file is available and mapped at a specific start address in the sender’s local memory map.
Offset |
Field |
Type |
Value Range |
Description |
|---|---|---|---|---|
0 |
|
|
|
Command Identifier |
4 |
|
|
|
Start address of the file |
8 |
|
|
|
Maximum size of the file in bytes |
12 |
|
|
|
File type descriptor (see below) |
14 |
|
|
|
Checksum algorithm (see below) |
16 |
|
|
Bytes |
32-byte digest payload (zero-padded if unused) |
48 |
|
String |
ASCII |
Null-terminated file name string |
The total size of the FileInfo structure is \(48 + ext{strlen(FileName)} + 1\) bytes. Because the maximum command length is 1024 bytes, the maximum file name length is 975 bytes (excluding the null terminator).
PublishSignedFile Command (RMF_CMD_PUBLISH_SIGNED_FILE):
Announces a cryptographically signed file. This command is typically used to publish .apx node definition files accompanied by an asymmetric digital signature for peer authentication.
Offset |
Field |
Type |
Value Range |
Description |
|---|---|---|---|---|
0 |
|
|
|
Command Identifier |
4 |
|
|
|
Start address of the file |
8 |
|
|
|
Maximum size of the file in bytes |
12 |
|
|
|
File type descriptor (see below) |
14 |
|
|
|
Cryptographic signature type (see below) |
16 |
|
|
Bytes |
64-byte cryptographic signature payload |
80 |
|
String |
ASCII |
Null-terminated file name string |
The fixed header size of PublishSignedFile is 80 bytes. The total structure size is \(80 + ext{strlen(FileName)} + 1\) bytes. The maximum file name length is 943 bytes (excluding the null terminator).
FileType Values¶
Value |
Identifier |
Description |
|---|---|---|
|
|
Fixed-size memory region (default for signals and definitions) |
|
|
Dynamically sized file with 8-bit length header |
|
|
Dynamically sized file with 16-bit length header |
|
|
Dynamically sized file with 32-bit length header |
|
|
Stream-backed device file |
|
|
Streaming FIFO queue |
DigestType Values¶
Value |
Identifier |
Description |
|---|---|---|
|
|
No checksum provided |
|
|
20-byte SHA-1 hash (padded to 32 bytes) |
|
|
32-byte SHA-256 hash |
SignatureType Values¶
Value |
Identifier |
Description |
|---|---|---|
|
|
No cryptographic signature provided |
|
|
64-byte raw ECDSA signature over NIST P-256 curve (concatenated 32-byte \(r\) and 32-byte \(s\) integers) |
Signed File Verification Flow¶
When a server is configured with require-signed-nodes = true:
Publication: The client sends
RMF_CMD_PUBLISH_SIGNED_FILEwithSignatureType = 1(ECDSA_P256) and the 64-byte signature extracted from the node’s companion.sigfile.Open Request: The server maps the remote file and sends
RMF_CMD_FILE_OPEN.Data Transmission: The client writes the complete
.apxdefinition payload to the remote address.Signature Verification: Upon receiving the full file (
MORE_BIT = 0), the server computes the SHA-256 hash of the payload and verifies the ECDSA signature against its list of configured trusted public keys.Acceptance / Rejection:
If verified: The server parses the definition and publishes corresponding
.in/.out/.cout/.cinfiles.If verification fails: The server transmits
RMF_CMD_NACKwithErrorCode = 80(APX_SIGNATURE_VERIFICATION_ERROR) and the node’s name, discarding the untrusted node.If an unsigned announcement (
RMF_CMD_FILE_INFO) is received for a node definition: The server rejects the node withErrorCode = 79(APX_SIGNATURE_MISSING_ERROR).
FileRevoke Command (RMF_CMD_REVOKE_FILE):
Unmaps a previously announced file. If the remote peer currently has the file open, it is automatically closed.
Offset |
Field |
Type |
Value |
Description |
|---|---|---|---|---|
0 |
|
|
|
Command Identifier |
4 |
|
|
|
Start address of the file to revoke |
Total size: 8 bytes.
Multiple FileInfo Packing:
Multiple FileInfo or PublishSignedFile structures may be packed into a single 1024-byte control write. When packing multiple structures:
Only the first structure includes the 4-byte
CmdTypefield.Subsequent structures begin immediately after the null terminator of the preceding file name (starting directly with
StartAddress).
Connection Lifecycle & Monitoring Commands¶
These commands are emitted by the server to connections operating in Monitor mode (Connection-Type: Monitor), allowing runtime diagnostic utilities (such as apx-info) to track client connections in real time.
ConnectionCreate Command (RMF_CMD_CONNECTION_CREATE):
Notifies monitoring clients that a new peer connection has connected and entered a given state.
Offset |
Field |
Type |
Value Range |
Description |
|---|---|---|---|---|
0 |
|
|
|
Command Identifier |
4 |
|
|
\(0\) – \(2^{32}-1\) |
Unique connection identifier |
8 |
|
|
|
Connection state (see below) |
9 |
|
String |
ASCII |
Null-terminated string label or client address |
Total size: \(9 + ext{strlen(ConnectionTag)} + 1\) bytes.
ConnectionState Values¶
Value |
Identifier |
Description |
|---|---|---|
|
|
Connection object created |
|
|
Physical socket connection established, greeting pending |
|
|
Protocol greeting accepted and active |
|
|
Connection terminated |
ConnectionRevoke Command (RMF_CMD_CONNECTION_REVOKE):
Notifies monitoring clients that an active connection has disconnected or has been closed.
Offset |
Field |
Type |
Value Range |
Description |
|---|---|---|---|---|
0 |
|
|
|
Command Identifier |
4 |
|
|
\(0\) – \(2^{32}-1\) |
Identifier of the revoked connection |
Total size: 8 bytes.
Diagnostic Commands¶
Used to verify transport liveness, measure round-trip latency, and test route paths.
Heartbeat Request (RMF_CMD_HEARTBEAT_RQST):
Offset |
Field |
Type |
Value |
Description |
|---|---|---|---|---|
0 |
|
|
|
Command Identifier |
Heartbeat Response (RMF_CMD_HEARTBEAT_RSP):
Offset |
Field |
Type |
Value |
Description |
|---|---|---|---|---|
0 |
|
|
|
Command Identifier |
Ping Request (RMF_CMD_PING_RQST):
Offset |
Field |
Type |
Value Range |
Description |
|---|---|---|---|---|
0 |
|
|
|
Command Identifier |
4 |
|
|
Address or |
Target file address ( |
8 |
|
|
|
Origin timestamp seconds |
12 |
|
|
|
Origin timestamp milliseconds |
Ping Response (RMF_CMD_PING_RSP):
Echoes back the fields from the corresponding Ping Request.
Offset |
Field |
Type |
Value Range |
Description |
|---|---|---|---|---|
0 |
|
|
|
Command Identifier |
4 |
|
|
Address |
Echoed target file address |
8 |
|
|
|
Echoed timestamp seconds |
12 |
|
|
|
Echoed timestamp milliseconds |
File Open & Close Commands¶
FileOpen Command (RMF_CMD_FILE_OPEN):
Requests to open a remote file announced via a preceding FileInfo or PublishSignedFile command.
Offset |
Field |
Type |
Value Range |
Description |
|---|---|---|---|---|
0 |
|
|
|
Command Identifier |
4 |
|
|
|
Start address of the remote file to open |
Total size: 8 bytes.
FileClose Command (RMF_CMD_FILE_CLOSE):
Closes a previously opened remote file.
Offset |
Field |
Type |
Value Range |
Description |
|---|---|---|---|---|
0 |
|
|
|
Command Identifier |
4 |
|
|
|
Start address of the remote file to close |
Total size: 8 bytes.
Comparison: RemoteFile v1.0 vs v1.1¶
The following table summarizes the protocol changes between RemoteFile v1.0 and RemoteFile v1.1:
Feature |
RemoteFile v1.0 |
RemoteFile v1.1 |
|---|---|---|
Greeting Header |
|
|
Greeting Framing Attr |
|
|
Greeting Role Attr |
None |
|
Handshake Response |
|
|
Error Signaling |
Empty |
Structured |
Signed File Publication |
Not supported |
|
Connection Monitoring |
Not supported |
|
Virtual File Types |
Fixed ( |
Fixed ( |
Backward Compatibility |
Client baseline |
Server supports both v1.0 and v1.1 clients simultaneously |