User Tools

Site Tools


packet:white-papers:pwp-0222

Packet White Paper: 222

Status: Informational
Date: June 2023
Author: Paula Dowie

Remote Host Protocol Version 2

Abstract

Remote Host Protocol (RHP) is one of the Application Programming Interfaces for the “XRouter” Amateur Packet Radio networking software. RHP allows applications, sited either locally to XRouter, or remotely from it, to use XRouter as a multi-protocol “packet engine”. RHP allows developers to write Packet Radio applications without having to write a Packet networking stack.

RHP version 1, described in [1] used an extensible binary packet format. This memo describes version 2, which uses JSON messages instead. Version 2 is more verbose than version 1, but is more suited to modern paradigms.

Status of This Memo

This memo provides information for the Packet Radio community. This memo does not propose a standard, but it describes an existing one. Distribution of this memo is unlimited.

Copyright © 2023 Paula Dowie. All rights reserved.

Table of Contents

- Introduction

  1. 1.1. Motivation
  2. 1.2. RHP Sockets
  3. 1.3. RHP2 Messages

- Overview of RHP2 Message Types - RHP2 Message Types In Detail

  1. 3.1. The AUTH Message
  2. 3.2. The AUTHREPLY Message
  3. 3.3. The OPEN Message
  4. 3.4. The OPENREPLY Message
  5. 3.5. The ACCEPT Message
  6. 3.6. The STATUS Message
  7. 3.7. The STATUSREPLY Message
  8. 3.8. The SEND Message
  9. 3.9. The SENDREPLY Message
  10. 3.10. The RECV Message
  11. 3.11. The CLOSE Message
  12. 3.12. The CLOSEREPLY Message
  13. 3.13. The SOCKET Message
  14. 3.14. The SOCKETREPLY Message
  15. 3.15. The BIND Message
  16. 3.16. The BINDREPLY Message
  17. 3.17. The LISTEN Message
  18. 3.18. The LISTENREPLY Message
  19. 3.19. The CONNECT Message
  20. 3.20. The CONNECTREPLY Message
  21. 3.21. The SENDTO Message
  22. 3.22. The SENDTOREPLY Message

- Address Formats

  1. 4.1. AX25 Family
  2. 4.2. NETROM Family
  3. 4.3. INET Family

- List of Error Codes - Typical Session Flow

  1. 6.1. Outgoing Connection
  2. 6.2. Incoming Connection

- Security Considerations - Caveats - Feedback - References

1. Introduction

RHP is the acronym for REMOTE HOST PROTOCOL, so called because it allows a “host” application to be located remotely from XRouter, effectively using XRouter as a multi-protocol “packet engine”.

The protocol allows applications, sited either locally to XRouter, or remotely from it, to access the XRouter protocol stack at many ISO layers, including layer 7, i.e. XRouter's command line interface.

The original RHP, described in [1], used an extensible binary packet format. It was perfectly adequate, but very few applications were developed to use it.

The world has moved on a long way since 2004. Today's application developers have little desire to craft binary packets, and it is likely that not many possess the skills to do so.

This memo describes RHP version 2 (RHP2), which uses JSON messages instead of binary ones, and outlines the JSON message format.

1.1. Motivation

The motivation for this protocol upgrade was the need to provide a modern socket-like API for the “XRouter” multi protocol Amateur Packet Radio networking software, and thus to stimulate the development of new applications.

Modern applications tend to be browser-based. The age of standalone applications is over, and very few “packeteers” are interested in command-line interfaces.

Whilst XRouter provides both HTTP and REST interfaces, both protocols have drawbacks. HTML pages tend to be fixed-format. The node author designs the pages, and the users are stuck with them. The sysop might be able to tweak the CSS, but the basic layout is set in stone. Node authors make terrible UI designers.

REST APIs are better, because they allow application developers to access the raw data, and display it however they wish. The data is decoupled from its presentation. Very little skill is required to write Javascript, hence there are plenty of UI developers capable of doing so. Hence more chance that someone will write a new UI.

Both HTTP and REST behave poorly when it comes to SESSIONS, as they are stateless by design. There are workarounds, but they are cumbersome and barely satisfactory.

RHP allows developers to write Packet Radio applications without having to write Packet Radio networking stacks. What's more, the applications don't have to run on the same machine or operating system as the Packet stack.

RHP is NOT a user interface. It is a machine-to-machine interface, mainly for ISO layers below the application layer. It treats XRouter as nothing more than a “packet engine”.

RHP version 2, sometimes referred to as “RHP2” uses JSON instead of a binary format, and adds the option of operation via Websockets. JSON is easy to read and debug, and modern languages have plenty of inbuilt support for both JSON and Websockets.

1.2. RHP Sockets

At the heart of RHP is the concept of “sockets”, i.e. communication endpoints. These are functionally similar to Berkeley (BSD) sockets, but with some extra features.

The diagram below depicts a client using RHP to control a socket, and to exchange data with it. In turn the socket is interacting with a target system using the AX25 protocol. Data is passed between the client and target via the socket, whilst RHP control signals pass only between client and server.

                     .--------------.
 .--------.          |  .--------.  |           .--------.
 | client |<----------->| socket |<------------>| Target |
 '--------'     RHP  |  '--------'  |   AX25    '--------'
                     '--------------'
                     Server (XRouter)

Sockets must be “opened” before use, and “closed” after use. When a socket is opened, a numeric “handle” is returned, which must be used for all subsequent operations via that socket.

When opening a socket, the client must specify a “protocol family”, and a “mode”.

The currently available protocol families are as follows:

Mnemonic Layer Usage
UNIX 7 XRouter CLI and applications
INET 3/4 TCP//UDP//ICMP//IP//DNS etc
AX25 2 AX25, APRS, Digipeating, custom protocols
NETROM 3/4 NetRom datagrams, streams, custom protocols

The available socket “modes” are as follows:

Mnemonic Meaning
STREAM Ordered, reliable octet stream (LAPB, TCP, CLI etc)
DGRAM Unreliable datagram (AX25 UI, UDP, NetRom L3 etc.)
SEQPKT Sequenced, reliable packets (AX25 only)
CUSTOM User specified protocol
SEMIRAW Addresses + raw payload
TRACE Decoded headers plus payload data
RAW Complete raw packet, no separate headers

Not all modes are available for all protocol families.

Within the AX25 family, stream mode would be used for normal AX25 connections, datagram mode for APRS, trace mode for monitoring packet activity, and raw mode for custom packet tracing / injection.

Within the NETROM family, stream mode would be used for normal L4 connections, DGRAM for NDP (NetRom Datagram Protocol) datagrams, CUSTOM for “protocol extension” frames, SEMIRAW for L3 headers plus payload, TRACE for tracing NetRom from layer 3 up, and RAW for raw layer 3 operations, such as Nodes and INP3 broadcasts.

Within the INET family, STREAM is for TCP connections, DGRAM for UDP, CUSTOM for IP datagrams transporting a specified protocol, TRACE for tracing up from IP layer, and RAW for generating / receiving IP datagrams without using XRouter's packet assembly/disassembly.

Clients may open multiple sockets at once, provided they are not identical. For example, a TRACE socket may be opened to monitor packet activity, while at the same time a DGRAM socket may be opened to send and receive UI frames, while several STREAM sockets may be opened, either to make connections to other systems, or to listen for incoming connections from them.

The only limitation is that a client cannot open more than one TRACE or RAW socket on the same PORT, or more than one DGRAM socket with the same PORT and LOCAL address, or more than one STREAM socket with identical PORT, LOCAL and REMOTE addresses.

Some of these limitations also apply to multiple CLIENTS. For instance, only ONE client may open a STREAM listener on the same port using the same local address. This is because XRouter would have no way of knowing which client to send the incoming packets to.

RHP sockets are “non-blocking”. For example, a connect request INITIATES a connection and returns the result of that operation, but the connection may not actually complete until some time later.

All sockets “owned” by a client are closed when the RHP client connection is terminated.

1.3. RHP2 Messages

Both versions of RHP use a single, persistent, TCP connection between the client and XRouter. The connection normally uses TCP port 9000, but this may be changed using the RHPPORT directive in XROUTER.CFG.

In RHP2, JSON “messages” pass bidirectionally across the TCP stream, to manage packet connections and transfer data in both directions.

The protocol may also be used via a Websockets connection, using the same TCP port number.

The endpoint for RHP2 over Websockets is ws://{host}:{port}/rhp, e.g. ws://localhost:9000/rhp. Future versions may duplicate this on the regular HTTP port.

Within “normal” RHP2, JSON messages are “framed” by a simple two-byte “frame length”, sent high byte first. e.g. the two bytes 0x01 0x20 indicate that the message which follows them is 288 bytes long.

 .---------------------------.
 | lenH | lenL | RHP Message |
 '---------------------------'
 Bytes:  1       1    <--- len --->
              RHP Message Framing

The framing for RHP2 in WebSockets is similar, albeit with a more complex header.

2. Overview of RHP2 Message Types

The most commonly used RHP2 message “types” are as follows:

Message Direction Description
AUTH Client to server Sends credentials to authenticate the client. Only required if the client has IP address in a public range, and is not whitelisted in ACCESS.SYS.
AUTHREPLY Server to client Indicates success/failure of auth request.
OPEN Client to server Initiates an “active” connection to a specific “target” system, or a “passive” listener to wait for incoming connections.
OPENREPLY Server to client Indicates success/failure of an OpenRequest, and returns a “handle” for further operations.
ACCEPT Server to client Conveys details of an incoming connection. Sent by “listener” sockets only.
STATUS Bidirectional Conveys flags such as “connected” and “busy”.
STATUSREPLY Server to client Indicates failure of a status request from client.
SEND Client to server Sends data to a target system with whom a connection has been established, in a format dictated by the MODE of the socket.
SENDREPLY Server to client Acknowledges a SEND message.
RECV Server to client Sends data, received from a connected target system, to the client. Each RECV message contains the payload from one packet.
CLOSE Client to server Requests closure of a socket or connection.
CLOSEREPLY Server to client Acknowledges closure of a socket or connection.

The following BSD-style message types are also supported:

Message Direction Description
SOCKET Client to server Opens a socket.
SOCKETREPLY Server to client Indicates success/failure of a SOCKET request, and returns a “handle” for further operations.
BIND Client to server Associates a local address with the socket.
BINDREPLY Server to client Indicates success/failure of BIND request.
LISTEN Client to server Initiates “listen” mode on a STREAM socket, awaiting incoming connections.
LISTENREPLY Server to client Indicates success/failure of LISTEN request.
CONNECT Client to server Initiates a connection to a target system (STREAM mode), or binds a remote address (DGRAM mode).
CONNECTREPLY Server to client Indicates success/failure of CONNECT request.
SENDTO Client to server Sends data to a target system (DGRAM mode only).
SENDTOREPLY Server to client Indicates success/failure of SENDTO operation.

3. RHP Message Types In Detail

All RHP2 messages MUST be in JSON format, beginning with the opening curly bracket { and ending with the closing curly bracket }.

Whitespace (spaces, tabs, newlines, etc.) is allowed within the JSON messages, but is not mandatory. Message examples in this document may include white space for clarity.

All fields of an RHP message are mandatory unless otherwise stated. The order of fields within a message is unimportant.

All messages MUST have a type field.

The id field is optional. If present in a request, XRouter ALWAYS replies, returning the same ID in the reply. Using a different ID in each request allows replies to be matched with the corresponding requests, allowing asynchronous “pipelining” of requests.

If the id field is omitted, the only replies, other than OPENREPLY, will be those that contain a non-zero error code.

3.1. The AUTH Message

The AUTH request sends credentials to authenticate the client. It is only required if the client has an IP address in a public range, and is not whitelisted by an entry in ACCESS.SYS.

Fields:

Name Type Value
type string “auth”
id integer (optional)
user string {user's callsign}
pass string {user's password}

Example:

{"type": "auth", "user": "g9zzz", "pass": "petunias"}

3.2. The AUTHREPLY Message

This message is sent from server to client, in response to an AUTH message or any other request received in unauthorised state.

Fields:

Name Type Value
type string “authReply”
id integer Same as request (if present)
errCode integer 0 or 14
errText string “Ok” or “Unauthorised”

If the usercall and password in an AUTH request match an entry in USERPASS.SYS, the value of errCode will be 0, and the value of errText will be “Ok”. Otherwise, the value of errCode will be 14, and the value of errText will be “Unauthorised”.

Examples:

{"type": "authReply", "id": 7, "errCode": 0, "errText": "Ok"}
{"type": "authReply", "errCode": 14, "errText": "Unauthorised"}

3.3. The OPEN Message

The OPEN request, from client to server, is used to open a socket, and optionally to initiate a connection or start a listener. It performs, in a single operation, the equivalent of the BSD SOCKET, BIND, LISTEN and CONNECT functions, depending on which fields are supplied.

Fields:

Name Type Value
type string “open”
id integer Serial number of request (optional)
pfam string Protocol family (see section 1.2)
mode string “stream”, “dgram”, “trace” or “raw”
port string port identifier (port number in XRouter)
local string Local address
remote string Remote address (active open only)
flags integer Option flags

Values for option flags:

Value Description
0x00 Passive open (listen)
0x01 Trace Incoming frames (modes RAW and TRACE)
0x02 Trace Outgoing frames (modes RAW and TRACE)
0x04 Trace Supervisory frames (mode TRACE only)
0x80 Active open (connect)

Passive open with unspecified remote accepts any call.
Passive open with remote address accepts only that address.

Example — open an AX25 connection to GB7GLO from callsign G8PZT-5:

{
  "type": "open",
  "id": 22,
  "pfam": "ax25",
  "mode": "stream",
  "port": 2,
  "local": "g8pzt-5",
  "remote": "gb7glo",
  "flags": 128
}

Example — open an AX25 TRACE socket on port 4:

{
  "type": "open",
  "id": 1,
  "pfam": "ax25",
  "mode": "trace",
  "port": "4",
  "flags": 7
}

3.4. The OPENREPLY Message

This message is sent from server to client in response to an OPEN request. It indicates success or failure of the request, and if the socket was successfully opened it returns a “socket handle” for further operations.

Fields:

Name Type Value
type string “openReply”
id integer Same as request (if present)
handle integer Socket handle
errcode integer Error code (0 = no error)
errtext string Error text in words, e.g. “Ok”

Example:

{
  "type": "openReply",
  "id": 22,
  "handle": 3,
  "errcode": 0,
  "errtext": "ok"
}

3.5. The ACCEPT Message

This message is sent from server to client, by “listener” sockets only. It conveys details of an incoming connection.

Fields:

Name Type Value
type string “accept”
seqno integer Sequence number of this message
handle integer Socket handle of the listener
child integer Socket handle of the new connection
remote string Remote (caller's) address
local string Local (listener) address
port integer XRouter port number of new connection

Example:

{
  "type": "accept",
  "seqno": 347,
  "handle": 3,
  "child": 7,
  "remote": "G4FPV-5",
  "local": "g8pzt-1",
  "port": 4
}

3.6. The STATUS Message

This message can be used in either direction. It can be sent asynchronously from server to client, to convey flags such as “connected” and “busy”. It can also be sent from client to server to request a status message from the server. In this second case, the server only sends a STATUSREPLY message if the request fails.

Fields (server to client):

Name Type Value
type string “status”
seqno integer Sequence number of this message
handle integer Socket handle
flags integer socket flags (server to client only)

Socket flags:

Name Value Description
CONOK 1 OK to accept (listeners only)
CONNECTED 2 Downlink is connected
BUSY 4 Not clear to send

Example (server to client):

{
  "type": "status",
  "seqno": 348,
  "handle": 3,
  "flags": 2
}

Fields (client to server):

Name Type Value
type string “status”
id integer Serial number of request (optional)
handle integer Socket handle

Example (client to server):

{
  "type": "status",
  "id": 23,
  "handle": 3
}

3.7. The STATUSREPLY Message

This message is only sent from server to client, only in reply to a STATUS request, and only if the request fails.

Fields:

Name Type Value
type string “statusReply”
id integer Same as request (if present)
handle integer Socket handle
errcode integer Error code
errtext string Error text

Example:

{
  "type": "statusReply",
  "id": 23,
  "handle": 3,
  "errcode": 12,
  "errtext": "Invalid handle"
}

3.8. The SEND Message

The SEND message sends data from client to server, for onward transmission to another system.

Fields:

Name Type Value
type string “send”
id integer Serial number of request (optional)
handle integer Socket handle
data string Data to be sent

Additional fields for datagram mode only:

Name Type Value
port string Destination port
local string Local address
remote string Remote address

Reserved and control characters in the data field MUST be JSON-escaped. The total size of the message MUST NOT exceed 65535 bytes.

Example:

{
  "type": "send",
  "id": 23,
  "handle": 3,
  "data": "Hello Fred, are you there?"
}

3.9. The SENDREPLY Message

The SENDREPLY message is sent from server to client in response to a SEND message, to convey the result of the operation.

Fields:

Name Type Value
type string “sendReply”
id integer Matches ID in SEND request (optional)
handle integer Socket handle
errcode integer Error number
errtext string Description of the error
status integer Status flags (STREAM only)

Status flags:

Name Value Description
CONNECTED 2 Downlink is connected
BUSY 4 Not clear to send

Example:

{
  "type": "sendReply",
  "id": 23,
  "handle": 3,
  "errcode": 0,
  "errtext": "Ok",
  "status": 2
}

3.10. The RECV Message

The RECV message is sent asynchronously from server to client, to convey data that has been received from a remote system. Each RECV message contains the payload from one AX25 packet. This message type is also used to convey TRACE data if the socket mode is TRACE.

Fields:

Name Type Value
type string “recv”
seqno integer Sequence number of this message
handle integer Socket handle
port string Port it was received on (datagram only)
action string “sent” or “rcvd” (RAW & TRACE only)
data string Data received from remote system

RAW and TRACE sockets can monitor both sent and received traffic, hence the action member.

Example RECV for a STREAM socket:

{
  "type": "recv",
  "seqno": 349,
  "handle": 3,
  "data": "Yes I'm here, what's up?"
}

Example trace representing [4] T: G8PZT-1>G8PZT: <RR R F R1>:

{
  "type": "recv",
  "seqno": 349,
  "handle": 1,
  "action": "sent",
  "port": "4",
  "srce": "G8PZT-1",
  "dest": "G8PZT",
  "ctrl": 33,
  "frametype": "RR",
  "rseq": 1,
  "cr": "R",
  "pf": "F"
}

3.11. The CLOSE Message

The CLOSE message is sent from client to server, to request closure of a socket or connection. It can also be sent asynchronously from server to client to inform the client that a connection has been closed by the remote link partner.

Fields:

Name Type Value
type string “close”
id integer (client to server only) (optional)
seqno integer Sequence number (server to client only)
handle integer Socket handle

Example (client to server):

{
  "id": 3,
  "type": "close",
  "handle": 3
}

Example (server to client):

{
  "type": "close",
  "seqno": 350,
  "handle": 3
}

3.12. The CLOSEREPLY Message

The CLOSEREPLY message is sent from server to client, in response to a CLOSE message, to acknowledge closure of a socket or connection.

Fields:

Name Type Value
type string “closeReply”
id integer Matches the one in the CLOSE request
handle integer Socket handle
errcode integer Error number
errtext string Description of the error

Example of a Successful Close:

{
  "id": 3,
  "type": "closeReply",
  "handle": 4,
  "errcode": 0,
  "errtext": "Ok"
}

Example of a Failed Close:

{
  "id": 3,
  "type": "closeReply",
  "handle": 0,
  "errcode": 12,
  "errtext": "Invalid handle"
}

3.13. The SOCKET Message

The SOCKET request is sent from client to server, to open a socket on the XRouter networking stack. It is similar to the OPEN request without the extra fields.

Fields:

Name Type Value
type string “socket”
id integer Serial number of request (optional)
pfam string Protocol family
mode string “stream”, “dgram”, “trace”, “raw” etc

For protocol family and mode values, see section 1.2.

Example — open an AX25 stream socket:

{
  "type": "socket",
  "id": 21,
  "pfam": "ax25",
  "mode": "stream"
}

Example — open a NetRom TRACE socket:

{
  "type": "socket",
  "id": 1,
  "pfam": "netrom",
  "mode": "trace"
}

3.14. The SOCKETREPLY Message

A SOCKETREPLY message is sent from server to client in response to a SOCKET request. It indicates the success or failure of the request, and if the socket was successfully opened it returns a “socket handle” for further operations.

Fields:

Name Type Value
type string “socketReply”
id integer Same as request (if present)
handle integer Handle of newly-created socket (*)
errcode integer Error code (0 = no error)
errtext string Error text in words, e.g. “Ok”

(*) The handle field is only present if the request was successful.

3.15. The BIND Message

The BIND request is sent from client to server, to associate a local address with the socket. Once bound, the local address may be used in subsequent LISTEN, CONNECT and SENDTO operations.

Fields:

Name Type Value
type string “bind”
id integer Serial number of request (optional)
local string Local address
port string port identifier (port number in XRouter)

The port field is only required for AX25. If supplied for other types of socket, that port MUST exist.

The local address MUST NOT be identical to any of XRouter's addresses (using the same callsign with a different SSID is OK).

If the socket is already bound, the request will fail.

3.16. The BINDREPLY Message

The BINDREPLY message is sent from server to client. It indicates the success or failure of a BIND request.

Fields:

Name Type Value
type string “bindReply”
id integer Same as request (if present)
handle integer Socket handle
errcode integer Error code (0 = no error)
errtext string Error text in words, e.g. “Ok”

3.17. The LISTEN Message

The LISTEN request is sent from client to server. On STREAM sockets it causes the socket to start waiting for incoming connections. On other types of socket, it begins the process of packet reception.

Fields:

Name Type Value
type string “listen”
id integer Serial number of request (optional)
flags integer Option flags

Values for option flags:

Value Description
0x01 Listen Incoming (modes RAW and TRACE)
0x02 Listen Outgoing (modes RAW and TRACE)
0x04 Trace Supervisory frames (AX25 TRACE only)

3.18. The LISTENREPLY Message

The LISTENREPLY message is sent from server to client. It indicates the success or failure of a LISTEN request.

Fields:

Name Type Value
type string “listenReply”
id integer Same as request (if present)
handle integer Socket handle
errcode integer Error code (0 = no error)
errtext string Error text in words, e.g. “Ok”

3.19. The CONNECT Message

The CONNECT request is sent from client to server. It initiates a connection to a target system (STREAM mode), or binds a remote address (DGRAM mode).

Fields:

Name Type Value
type string “connect”
id integer Serial number of request (optional)
remote string Remote address

A local address MUST be bound before CONNECT is issued. XRouter does not auto-bind local addresses.

3.20. The CONNECTREPLY Message

The CONNECTREPLY message is sent from server to client. It indicates the success or failure of a CONNECT request.

Fields:

Name Type Value
type string “ConnectReply”
id integer Same as request (if present)
handle integer Socket handle
errcode integer Error code (0 = no error)
errtext string Error text in words, e.g. “Ok”

3.21. The SENDTO Message

The SENDTO request is sent from client to server. It sends data to a specified target system. It is allowed only on DGRAM sockets.

If a local address is bound, only the remote address need be supplied and vice versa. If both addresses are bound, the SEND request may be used instead. Addresses that are specified in the SENDTO request take precedence over any bound addresses.

Fields:

Name Type Value
type string “sendto”
id integer Serial number of request (optional)
handle integer Socket handle
data string Data to be sent (*)
port string Destination port
local string Local address
remote string Remote address
tos integer Type of service (INET only)

(*) Reserved and control characters in the data field MUST be JSON-escaped. The total size of the message MUST NOT exceed 65535 bytes.

Example for AX25 DGRAM socket, with bound local address and port:

{
  "type": "sendto",
  "id": 23,
  "handle": 3,
  "remote": "g1frd-6",
  "data": "\U0008Hello Fred, are you there?\r"
}

3.22. The SENDTOREPLY Message

The SENDTOREPLY message is sent from server to client. It indicates the success or failure of a SENDTO operation. A SENDTO might fail if the handle is missing or invalid, or an address is missing or invalid, or if the transmit queue is too full. In the latter case the message may succeed if retried later.

Fields:

Name Type Value
type string “sendtoReply”
id integer Same as request (if present)
handle integer Socket handle
errcode integer Error code (0 = no error)
errtext string Error text in words, e.g. “Ok”

4. Address Formats

The format of addresses supplied in local and remote fields depends on the address family as follows:

4.1. AX25 Family

The AX25 family uses simple callsigns, e.g. g8pzt-1.

4.2. NETROM Family

The format for NETROM addresses is:

<usercall>[@nodecall][:svcnum]

Where svcnum is the NetRomX “service” number (Reference [2]).

Examples: g8pzt-1@g8pzt or gb7pzt:23

4.3. INET Family

The format for INET family addresses is <ipaddress>[:port]

Examples: 44.131.91.2 or 192.168.3.22:25

5. List of Error Codes

You are advised to parse the error CODE, not the error text, as the latter may change in future versions.
Code Text Notes
0 “Ok” No error
1 “Unspecified” Catch-all error, might be transient
2 “Bad or missing type” Unrecognised frame type, don't retry
3 “Invalid handle” Invalid socket handle, don't retry
4 “No memory” No memory, try later
5 “Bad or missing mode” Invalid “mode” in SOCKET or OPEN
6 “Invalid local address” (in OPEN, SOCKET, or BIND)
7 “Invalid remote address” (in OPEN or CONNECT)
8 “Bad or missing family” Unsupported address family
9 “Duplicate socket” Socket / connection already exists
10 “No such port” Invalid port number in OPEN or BIND
11 “Invalid protocol” (in OPEN or SOCKET)
12 “Bad parameter” Bad or missing parameter
13 “No buffers” Output queue full (retry later)
14 “Unauthorised” Request requires AUTHorisation
15 “No Route” No route to target (L4 / TCP open)
16 “Operation not supported” e.g. SEND on a TRACE socket

6. Typical Session Flow

This section outlines the general flow of different types of session. It assumes that the client has already established connection with the server, either via direct TCP connection, or via Websockets, and has authenticated if necessary.

6.1. Outgoing Connection

An outgoing connection would proceed as follows:

- Client sends OPEN message, specifying the radio port, plus source and destination calls (including digipeaters if required). - Server immediately replies with OPEN_REPLY, containing a socket “handle” for all subsequent operations on the socket. - If the connection succeeds, the server asynchronously sends a STATUS message indicating “connected”. If the connection fails, the status message contains “disconnected” instead. - The client sends data to the connection using SEND messages, the payload of which is JSON-escaped so it can handle full binary. - SEND messages are acknowledged using SEND_REPLY. - If the client sends too much data for the AX25 link to handle, the server sends a STATUS message with the BUSY flag set. When clear to send again, the server sends a STATUS message with the BUSY flag unset. - Data received from the downlink is sent to the client in RECV messages, with the payload JSON-escaped. - If the downlink initiates a disconnect, the server sends a STATUS message to the client with the CONNECTED flag set to “false”. The client must now issue a CLOSE to dispose of the socket. - Alternatively, if the client wishes to terminate the connection it issues a CLOSE request, and the server responds with a CLOSE_REPLY.

6.2. Incoming Connection

An incoming connection proceeds as follows:

- The client sends an OPEN message, specifying the XRouter PORT number and the local callsign. This creates a “listener” socket. - The server responds with an OPEN_REPLY message containing the socket handle (or an error code). - If someone connects to the callsign associated with the socket, the server immediately sends an ACCEPT message to the client, containing the socket handle and the callsign of the connectee. - The remainder of the connection proceeds as in step 4 of the Outgoing Connection flow above.

7. Security Considerations

By default, RHP only allows usage by clients with “localhost” and “LAN” IP addresses. In this context LAN addresses are those in the ranges 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16.

Clients with non-LAN IP addresses MUST authorise, by sending a valid AUTH packet before they can use any other RHP commands. The AUTH packet MUST contain a username/password pair which matches one stored in USERPASS.SYS.

Non-LAN clients MAY be granted access without AUTH by including the client's IP address in ACCESS.SYS. Beware of granting such access to ranges of IP addresses, unless you have control of that range.

At the time of writing, authorisation uses plain text usernames and passwords, simply because RHP was never intended for use on the public internet. Alternative authentication methods are planned for future versions.

8. Caveats

As this document is a first draft, it may be vague, incomplete or inaccurate. If it is not fit for purpose, please send feedback, to ensure the next draft is an improvement.

Not every use case has been exhaustively tested, so there may still be bugs in XRouter's implementation of RHP2. Please report them.

9. Feedback

Please send comments, criticisms, suggestions, hate mail etc to the following email address:

[email protected]

10. References

[1] Dowie P., “Remote Host Protocol”, PWP 144, December 2004.
[2] Dowie P., “NET/ROM Data Multiplexing”, PWP 109, July 2001.


PWP222 Remote Host Protocol Version 2 — June 2023

packet/white-papers/pwp-0222.txt · Last modified: by m0lte