User Tools

Site Tools


packet:white-papers:pwp-0245

Packet White Paper: 245

AI extraction from PDF.

Status: Informational
Date: May 2024
Author: Paula Dowie

RHP Version 2 - AX25 Functionality

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”.

This memo, aimed at application developers, is a brief guide, which describes only the AX25-layer functionality of RHP version 2. Some information has been omitted for clarity. For a full description of RHP version 2 see reference [2] “Remote Host Protocol”, PWP 222.

Status of This Memo

This memo provides information for the Packet Radio community. This memo does not specify a standard of any kind. Discussions and suggestions are welcomed. Distribution of this memo is unlimited.

Copyright © 2024 Paula Dowie. All rights reserved.

Table of Contents

  1. Introduction
    1. 1.1. RHP Sockets
  2. Overview of RHP Message Types
  3. RHP 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
  4. List of Error Codes
  5. Typical Session Flow
    1. 5.1. Outgoing Connection
    2. 5.2. Incoming Connection
  6. Websocket Endpoint
  7. Security Considerations
  8. 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. However this document concerns only AX25 level 2.

RHP version 1, described in [1] uses an extensible binary packet format. Although efficient, it has been superseded by version 2, which passes JSON messages instead. Version 2 is more verbose, but more suited to modern paradigms.

This document outlines the JSON message format, normally used over a simple TCP connection to XRouter's port 9000. This port number is specified using the RHPPORT directive in XROUTER.CFG. The protocol may also be used via a WebSockets connection, using the same port number.

RHP2 is a client-server protocol which uses JSON “messages” in a persistent TCP stream, to manage packet connections and transfer data in both directions.

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.

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

1.1. 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”, in this case “AX25”, and a “mode”.

There are 4 main socket “modes” applicable to AX25, as follows:

Mode Description
STREAM AX25 connected mode
DATAGRAM AX25 unconnected mode (UI frames)
RAW AX25 un-decoded raw packet data
TRACE AX25 decoded headers plus data

Stream mode would be used for normal AX25 connections, datagram mode for APRS, trace mode for monitoring packet activity, and raw mode for doing your own packet tracing / injection.

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 (callsign-ssid), 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 callsign. This is because XRouter would have no way of knowing which client the incoming packets belonged to.

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

2. Overview of RHP Message Types

The most commonly used RHP 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 AX25 station, 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 from client to radio, encapsulated in AX25 numbered information frames (for STREAM sockets) or UI frames for DGRAM sockets.
SENDREPLY Server to client Acknowledges a SEND message.
RECV Server to client Sends data from radio to client. Each RECV message contains the payload from one AX25 packet.
CLOSE Client to server Requests closure of a socket or connection.
CLOSEREPLY Server to client Acknowledges closure of a socket or connection.
NOTE: Additional BSD-style message types SOCKET, BIND, LISTEN, CONNECT, SENDTO etc may be used, but have been omitted for clarity.

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 }.

White space (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.

Fields:

Name Type Value
type string “open”
id integer Serial number of request (optional)
pfam string “ax25” (protocol family)
mode string “stream”, “dgram”, “trace” or “raw”
port string port identifier (port number in XRouter)
local string Local callsign
remote string Remote callsign (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 GB7NXT from callsign G8PZT-5:

{
  "type": "open",
  "id": 22,
  "pfam": "ax25",
  "mode": "stream",
  "port": 2,
  "local": "g8pzt-5",
  "remote": "gb7nxt",
  "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) callsign
local string Local (listener) callsign
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 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"
}

4. 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

5. 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.

5.1. Outgoing Connection

An outgoing connection would proceed as follows:

  1. Client sends OPEN message, specifying the radio port, plus source and destination calls (including digipeaters if required).
  2. Server immediately replies with OPENREPLY, containing a socket “handle” for all subsequent operations on the socket.
  3. If the connection succeeds, the server asynchronously sends a STATUS message indicating “connected”. If the connection fails, the status message contains “disconnected” instead.
  4. The client sends data to the connection using SEND messages, the payload of which is JSON-escaped so it can handle full binary.
  5. SEND messages are acknowledged using SENDREPLY.
  6. 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.
  7. Data received from the downlink is sent to the client in RECV messages, with the payload JSON-escaped.
  8. 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.
  9. Alternatively, if the client wishes to terminate the connection it issues a CLOSE request, and the server responds with a CLOSEREPLY.

5.2. Incoming Connection

An incoming connection proceeds as follows:

  1. The client sends an OPEN message, specifying the XRouter PORT number and the local callsign. This creates a “listener” socket.
  2. The server responds with an OPENREPLY message containing the socket handle (or an error code).
  3. 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.
  4. The remainder of the connection proceeds as in step 4 of the Outgoing Connection flow above.

6. Websocket Endpoint

The endpoint for RHP over WebSockets is ws://{host}:{port}/rhp, e.g. ws://localhost:9000/rhp (this may change in future, as it would make more sense to use XRouter's web server port for everything).

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. This will be rectified in future versions.

8. References

  1. Dowie P., “Remote Host Protocol”, PWP 144, December 2004.
  2. Dowie P., “Remote Host Protocol Version 2”, PWP 222, June 2023.

PWP245 RHP version 2 AX25 Functionality — May 2024

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