24  Remote access

org.arl.unet.Services.REMOTE

24.1 Overview

The REMOTE service provides higher-level data services across the network: text messaging, file transfer and remote command execution. It builds on the TRANSPORT service (Chapter 23), and adds metadata such as MIME types, mailboxes, message classes and threaded responses. These remote messages and their attributes are explored in detail in Chapter 8. The default remote access agent is accessed as remote.

Note

File transfer and remote command execution access the node’s filesystem and shell, and are disabled by default. They are enabled by setting remote.enable = true on the node being accessed.

Warning

Be clear about what enable opens up: the default remote access agent implements no authentication. Once enabled, the node honors every file and command request that arrives over the network — any node that can reach it can read and write its files and run shell commands on it. (The RemoteExecReq message carries a credentials field, but the service does not specify how authentication should work; the default implementation ignores it.) Enable remote access only on networks where every node is trusted.

Tip

For a basic layer of protection against outsiders, some commercial modems support a physical layer scrambler: setting phy[].scrambler to a common secret 64-bit seed on all your nodes whitens every frame with it, so modems without the seed cannot decode your traffic (Chapter 17). Be aware of its limits — it is not cryptographically strong, and does not protect against playback attacks — but it keeps a casually configured third-party modem from joining your network.

24.2 Messages

Agents providing this service honor the following requests:

  • RemoteMessageReq – send a remote message

    Field Type Default Remarks
    data byte[]
    from int 0 internal use only
    mailbox string mailbox name (used with TTL_MAILBOX)
    messageClass string user-defined class for rule-based routing
    mimeType string application/octet-stream content type (default application/octet-stream)
    priority Priority NORMAL
    progress boolean false
    protocol int 0
    reliability boolean
    remoteRecipient string agent ID or topic on the remote node
    robustness Robustness NORMAL
    route string
    shortcircuit boolean true
    to int 0
    ttl float NaN time-to-live in seconds
  • RemoteTextReq – send a text message (chat)

    Field Type Default Remarks
    data byte[]
    from int 0
    mailbox string
    messageClass string
    mimeType string application/x-chat
    priority enum NORMAL
    progress boolean false
    protocol int 0
    reliability boolean
    remoteRecipient string
    robustness enum NORMAL
    route string
    shortcircuit boolean true
    text string text message to send
    to int 0
    ttl float NaN
  • RemoteExecReq – execute a command on a remote node

    Field Type Default Remarks
    command string command to execute
    credentials string authentication credentials, if required
    data byte[]
    from int 0
    mailbox string
    messageClass string
    mimeType string application/x-command
    priority enum NORMAL
    progress boolean false
    protocol int 0
    reliability boolean
    remoteRecipient string
    robustness enum NORMAL
    route string
    shortcircuit boolean true
    to int 0
    ttl float NaN
  • RemoteFilePutReq – send a file (or data) to a remote node

    Field Type Default Remarks
    credentials string
    data byte[] data to write (if not sending a local file)
    filename string remote file name
    localFilename string
    priority enum NORMAL
    progress boolean false
    resume boolean true true to resume an interrupted transfer
    to int -1
  • RemoteFileGetReq – retrieve a file (or data) from a remote node

    Field Type Default Remarks
    credentials string
    filename string remote file name
    localFilename string local file name (empty to receive as data)
    priority enum NORMAL
    progress boolean false
    resume boolean true true to resume an interrupted transfer
    to int -1

Each request is answered with an AGREE once accepted (a REFUSE if invalid, a FAILURE if something goes wrong); the operation itself then proceeds over the network, and its outcome is reported to the requester:

  • RemoteFailureNtf – remote operation failed

    Field Type Default Remarks
    reason string reason for failure
  • RemoteFileNtf – file (or data) received from a remote node

    Field Type Default Remarks
    data byte[]
    filename string
    from int -1
    transferDuration float NaN

On the receiving node, an incoming remote message is delivered as a RemoteMessageNtf (or, for chat messages, a RemoteTextNtf) published on the global Topics.DATAGRAM topic — unless the sender named a remoteRecipient, in which case it is delivered to that agent or topic directly. Replies (inReplyTo set) are delivered back to the agent that sent the original message. A remote node that receives a command or file request while its enable flag is off responds with a RemoteFailureNtf instead of executing it.

24.3 Parameters

The parameters of the REMOTE service are implementation-specific (see the implementation section below for those of the default agent). The key contract parameter is enable, which gates remote command execution and file access.

24.4 Commands

  • tell – send a text message to remote node

    Example:

    tell 2, 'hello'         // send text message to node 2
    tell 2, 'hello', true   // send reliable text message to node 2
    
  • fget – get file from remote node

    fget can only get files from nodes with remote.enable = true.

    Example:

    fget 3, 'abc.txt'       // get file abc.txt from node 3
    fget 3, 'abc', 'abc2'   // get file abc from node 3 as abc2
    fget 3, 'abc', ''       // get file abc from node 3 as byte[]
    
  • fput – put file on remote node

    fput can only put files to nodes with remote.enable = true.

    Examples:

    fput 2, 'a.txt'         // send file a.txt to node 2
    fput 2, 'abc', 'abc2'   // send file abc to node 2 as abc2
    
  • rsh – run shell command on remote node

    rsh can only execute commands on nodes with remote.enable = true. The output of the command is sent back to the local node. If this is not desired, end the command with a semicolon.

    Example:

    rsh 3, 'reboot;'        // ask node 3 to reboot itself
    rsh 3, 'reboot;', true  // reliably ask node 3 to reboot itself
    rsh 3, 'phy.MTU'        // ask node 3 to send me the value of phy.MTU
    rsh 3, 'ls'             // ask node 3 to send me the list of files
    
  • progress – enable/disable progress reporting for remote file transfers

    Examples:

    progress on     // enable progress reporting for fget
    progress true   // enable progress reporting for fget
    progress off    // disable progress reporting for fget
    progress false  // disable progress reporting for fget
    progress        // check current setting for progress reporting

24.5 Examples

Start the 2-node-network, and connect to node A’s shell. The remote node (node B, address 31) must have remote access enabled before it will honor shell or file operations:

> remote.enable = true
true

Back on node A, send a text message to node B, where it pops up on the shell:

> tell host('B'), 'surfacing now'
OK
[232]: surfacing now

Run a command remotely: the rsh command asks node B to execute a command — here, lowering its transmit power:

> rsh 31, 'plvl -20'
OK

A few seconds later (after the command has crossed the network and the remote node’s execDelay has elapsed), reading the parameter on node B confirms it was executed:

> plvl
phy[1].powerLevel = -20.0
phy[2].powerLevel = -20.0
phy[3].powerLevel = -20.0
phy[4].powerLevel = -20.0
phy.powerLevel = [-20.0]

File transfers work the same way — fput sends a local file to the remote node, and fget retrieves a remote file, with a RemoteSuccessNtf or RemoteFileNtf reporting completion. The transcript below is illustrative (it assumes data.csv exists on node A and results.log on node B):

> fput 31, 'data.csv'
AGREE
RemoteSuccessNtf:INFORM[to:31]
> fget 31, 'results.log'
AGREE
RemoteFileNtf:INFORM[from:31 filename:results.log (412 bytes)]

24.6 Implementation

24.6.1 Caddy / CaddyLite (transport, remote)

Class Services Capabilities Availability
CaddyLite REMOTE, TRANSPORT, DATAGRAM RELIABILITY, FRAGMENTATION, CANCELLATION, PROGRESS, COMPRESSION default stack
Caddy REMOTE, TRANSPORT, DATAGRAM as above, plus PRIORITY, TTL, FAIRNESS commercial license

The default implementation is loaded as part of the default stack (Chapter 13) under the agent name caddy, and is most often used through its transport (transport service) and remote (remote service) shell handles. In addition to the REMOTE service described above, the same agent provides the TRANSPORT (Chapter 23) and DATAGRAM (Chapter 16) services. The base agent is CaddyLite; a licensed Caddy agent extends it with additional features (see the callout below).

24.6.1.1 How it works

Where a link delivers data to an immediate neighbor, the transport service delivers it all the way to a destination that may be several hops away, using the ROUTING service to choose the path. Two problems that the link layer cannot solve on its own are handled here. First, large datagrams are fragmented for transmission and reassembled at the destination, so an application can send payloads far larger than a single link frame; each fragment carries a compact transaction-and-fragment header, and a receiver that sees fragments arrive out of order abandons the transaction. Second, reliability is end-to-end: the destination acknowledges what it receives and the source retransmits what is lost, which is necessary because a datagram delivered reliably across each individual hop can still be lost if an intermediate node fails. The source waits up to ackTimeout for an end-to-end acknowledgement before retransmitting, and gives up after retry attempts. Outgoing datagrams are serviced from a queue, and large ones may be compressed before transmission.

The remote-access features map onto this reliable transport. Remote shell commands, text messages and file get/put are carried as transport datagrams; file transfers use a short handshake to exchange file information before the data flows. A command received from a remote node is run after a short execDelay (a safety margin), groovy controls whether such commands are interpreted as Groovy, cwd sets the working directory for file transfers, and retryDelay governs how long the agent waits before retrying when a route is temporarily unavailable. Remote operations are only honored when enable is set, and the agents this one builds on are named by dsp (the datagram/transport provider) and shell (the shell used to execute remote commands).

24.6.1.2 Parameters

  • dsp – datagram service provider agent name

  • shell – shell service provider agent name

  • enable – enable remote file/shell operations (default: false)

  • groovy – enable Groovy extensions for shell commands (default: true)

    When Groovy extensions are enabled, rsh commands can use a me variable to denote the requesting node address.

    Example:

    rsh 3, 'tell me,"hello!"'    // ask node 3 to send a text message to me
    
  • execDelay – delay before executing a command (seconds)

  • retryDelay – delay before retrying an unavailable route (seconds)

  • compress – enable compression for large datagrams

  • cwd – working directory to load/save files

  • ackTimeout – timeout for end-to-end ACKs (seconds)

  • retry – maximum retry attempts for datagram fragments

24.6.1.3 Usage notes

NotePremium feature

The base CaddyLite agent provides reliable multi-hop transport, remote access and file transfer, and is part of the standard distribution. The licensed Caddy agent is a drop-in replacement that adds:

  • Quality of Service (QoS) — datagram priority, time-to-live (TTL) and fairness, together with user-defined routing rules for selecting routes per message; and
  • Resumable file transfers — an interrupted file get/put resumes from where it left off, rather than restarting.

These are premium features (see Section 13.3). When the licensed Caddy agent is present, setup.groovy loads it automatically in place of CaddyLite; otherwise the base agent is used.

  • ping and the remote shell/file/text commands all use this agent; it is reachable as transport (transport service) and remote (remote service).
  • Enable remote shell/file operations (enable) only on nodes where you trust remote access.
  • Raise ackTimeout on long multi-hop paths where end-to-end acknowledgements take longer to return.