Remote Applications

[ about | screenshots | structure | interface | configuration | download | related ]

About RAPP


(Remote APPlications) is a way of doing remote application deployment in a fairly simple way. There are plenty of things in this arena already, but I thought I'd add to it anyway. It's now in a kinda-working state, but the code that's there needs some tidying up -- something for when there's more time.

Rationale: It's probably worth mentioning a few words about why this exists (for my own justification if no-one elses!). Every time I've written a graphical application, and with little exception, it's been a mess. Generally speaking, the way in which humans interact with graphical user interfaces is far detached from the logic of the program underneath it. GUIs have a kind of concurrent behaviour; the user can click on any button at any time (more or less), generating actions that the program must respond to. Object-oriented environments (e.g. Java/Swing and C++/WG) typically tie interface components to "objects" in the program. Lovely abstraction, but the concurrent aspect of interfaces breaks this somewhat. Either it's free-range concurrency (e.g. the "event thread" with Swing), or strict serialisation through an event loop (e.g. what WG and many other toolkits do). The most fitting language is one that is itself concurrent (e.g. occam-pi), since autonomous "processes" can be used to represent interface components. Simple interfaces are manageable with either technique, to a greater or lesser degree, but things get increasingly less pleaseant as the interface complexity grows. A typical example might be some kind of control interface, where some data is updated in real-time, the user is interacting (clicking buttons, etc.), and those interactions cause other parts of the interface to change. Altogether, it's not an entirely nice situation for the application program. RAPP is an attempt to make the application/interface bridge a little nicer for the application. The theory is that if an application and its interface are detached in some way, the scope for what can go wrong in their linkage is limited. It does mean, however, that the interface side needs to be aware of some extra (application related) things, e.g. that clicking a certain button should "suspend" the interface until it is updated (preventing the user from clicking other buttons etc. in the meantime).

Download and Installation

Version 0.2.0 of rapp and rappd require UWG 0.2.0 or later.

From version 0.1.3, you'll need to tell rappd and rapp where UWG is installed when configuring. Rappd still expects to be run from its distribution tree -- you can install it elsewhere, but will need to edit the various configuration files it installs (for the time being). Ordinarily, for example:

    bash:~/rapp-0.2.0/$ ./configure --with-uwg-config=/home/fred/uwg/include/uwg
    ...  configure output
    bash:~/rapp-0.2.0/$ make

Version 0.2.0: the distribution ships with two keypairs; one for the server and one for the user. The passphrase in both cases is "default".


RAPP authentication module window RAPP client-side explorer RAPP chat application and authenticated user

The authentication module in RAPP 0.2.0, using public-private key pairs; user supplies passphrase and off it goes.

Moderately recent 'RAPP explorer' addition, now mostly working, client-side file browser effectively; understands about .rapp files on the server -- some icons built-in, some downloaded [icons shamelessly copied from afterstep/gnome/debian directories]

Modified chat application (python script) which now understands about authenticated users ('frmb' in this case)

rapp house-monitor application

This is an output-only bash script (actions sent by the client are absorbed in rappd). The interface contains a series of label gadgets that get updated by the script, e.g.:

    <gadget type="UWGLabel" name="utilitytemp">
        <property name="geometry" value="260,164,128,16" />
        <property set="cpref" />
        <property set="helvfont" />
        <property name="background" value="black" />
        <property name="foreground" value="white" />
        <property name="alignment" value="left" />
        <property name="caption" value="0.0" />

rapp test application

The iotest application (fed from another shell-script):

This pretty basic application uses a bit of awk to process interaction -- more or less to demonstrate that I/O works, probably more sensible to use python or perl.. The script is downloadable here, but kind of:

    printf '%s\n' "$REPLY" | awk -F : '{
        if ($1 != "iotest") {
            printf ("::BEGIN\n");
            printf ("<update name=\"thelabel\">\n");
            printf ("<property name=\"caption\" value=\"erk, not me! [%s]\" />\n", $0);
            printf ("</update>\n");
            printf ("::END\n");
        } else {
    }' || break

rapp multi-client chat application rapp server control module supporting multiple sessions

A very basic multi-client chat application. The application logic used to be a bit of bash script, but has now been re-written in Python (0.1.3 version).

This is the start of a server-control module, implemented as a plug-in library. The initial XHPD interface can be downloaded here, updates are generated from within the C code.

This shows a collection of things going on in the RAPP client.


rapp structure

The original structure of rapp was to have applications broken into two pieces. The client side (rapp) providing an interface for some application running on the server side (rappd). This has been expanded on a bit, to provide a range of interfacing mechanisms at either side -- the way the whole thing works should make this quite possible. The figure on the right shows the modified structure (and what the software is heading towards):

The key piece is the rapp-server (rappd). Applications attach on one side, clients on the other. The transport between a rapp client and the server is TCP -- over a network such as the internet, or some intranet (or through a UNIX socket locally). The server sends the rapp client descriptions of interfaces (and control information). When the user interacts with the interface (clicking a button for example), the rapp client sends an event back to the server, which notifies the underlying application. The amount of network interaction can be controlled by the application, by selecting only the events it is interested in.

Due to latency introduced from networks and heavily-loaded servers, applications might not be instantly responsive (although it can be indicated to the user that the application is waiting for a server response). Thus, this is not going to be suitable for certain things (quake-2 style games, for example).

Application Interfaces

There are a range of server interfaces, some implemented, most not (yet). Within the rapp-server code these are referred to as "session engines".

Client Interfaces

The various rapp clients connect to the server and exchange XHPD blocks only (which might not be as UWG-specific as they were originally).


I'm now using micro-WG. The interface descriptions are sent as XHPD blocks -- XML-HPD. XHPD is just an XML encoding of the traditional WG HPD file. This gets parsed and rendered by rapp (using expat or UWG's own -- and simple -- parser to do the XML parsing). In essence, rapp is a UWG application. The server-side needs to be linked with UWG (for some of the non-visual gadgets), but doesn't need any X11 support at run-time. All the server has to do is generate interface descriptions with appropriate control information, interpret the events being sent back, and from that update the interface appropiately. You can use UWGBuilder for designing interfaces.

One potential target application is wireless hand-held devices, running a small X server + rapp (or some other rendering agent which understands the XHPD-style stuff and protocols used), giving convenient access to large applications, which wouldn't normally be possible for such small devices. I'd like to use the lcars-gadgets to provide something like a sony-viao with a home-control system, lights, TV, etc.; that would rock.

The rapp server supports a session mechanism, the idea being that a client can save the state of a session, disconnect, come back later and restore the session. Amongst other things, this provides a nice way to break apart back-end handlers from rappd. To this end, rappd has a series of session-engines. The only one currently implemented is the "external engine". This provides a mechanism to launch an external program and use its standard input/output to communicate with the rapp client. It's pretty basic, but so far appears to work ok :-).


From version 0.2.0, the configuration is held in an XML file called "rappd-config.xml", which is searched for in the current directory (or specified on the command-line). The supplied configuration is setup to run the server in its distribution tree, having been started on the command-line.

When the client starts up without a specific file, it produces a file-selector which can be used to browse the rapp file-system (or any other). If an XHPD file is selected (from rappd or elsewhere), the client simply renders it (with whatever local processing the file contains). Mainly intended for development, testing and general viewing of XHPD files. If the client selects a ".rapp" file from the rapp file-system only, a new session on the server is started.

Version 0.2.0: the RAPP client now contains an 'explorer' style interface, allowing the user to browse files on the server. If used ('-E' command-line option), it runs separately to sessions, allowing multiple sessions to be started by the client. The browser reads the '.rapp' files found on the server and extracts descriptions and icons for them. Clients can also now authenticate with the server, acquiring 'tokens' (e.g. "trusted-user" for logging in). These are defined in the configuration file along with the users. The authentication module's client-side '.rapp' file contains, for example: The example "monitor.rapp" file, that the client downloads whole, contains:               "auth"
    rapp.description:        "RAPP authentication"
    rapp.async:              1
    rapp.icon:               "rapp:///images/auth.xpm"

The important setting is "name" -- this gives the name of the session on the server side (which the client asks for). The various session definitions are held in the server's "modulepath". For the monitor application, this is again called "monitor.rapp" (generally "X.rapp" where "X" is the "" setting), and for the authentication module, contains:

    rapp.engine:                 module

    rapp.modengine.module:       "rappmods/"
    rapp.modengine.multiclient:  no
    rapp.modengine.sessdir:      "file://modfiles/auth"

As another example, the house-monitoring application (which gives a read-out of the temperature, electricity usage, etc.) uses:

    rapp.engine:             external       output-only
    rapp.extengine.exec:     "scripts/"

The "engine" setting specifies which session-engine is to be used. The only engines currently implemented are the external and module ones. The external engine launches an external program; the module engine loads pre-compiled code into the RAPP server. The "" setting describes how the program given in "extengine.exec" interacts with the client. The example given (for house-monitoring) is output-only -- it just updates the contents of various labels on the client window. The executable given in "extengine.exec" must be something that a UWGChildProcess can run -- i.e. something on the local file-system.

Another script (added for 0.1.3) produces a window with some buttons that react when pressed. The .rapp module file for this contains the additional setting:

    rapp.extengine.actions:  formatted

This causes the external engine to pre-process actions sent by the client. In the current implementation (between 0.1.2 and 0.2.0) this involves parsing the XHPD actions sent from the client and extracting the "value" field -- all properties/etc. sent back are ignored. Strings sent to the external program will be things like "iotest:button1:on_click".

From 0.1.3 the external engine can handle multi-client applications. From 0.2.0 so can the module engine. This is enabled by the following setting:

    rapp.extengine.multiclient:  yes

The external program receives notifications of joining and leaving (client) sessions, and is automatically shut-down when the last client leaves. Output can either be sent to all clients or just to a single one; input is prefixed by the session ID.

Related Stuff

There are various similar/related bits of software out there. Here's an attempt to list some of them (if you find any I've missed, please let me know :-)).

Last modified: Sun Dec 3 20:40:06 2006 by Fred Barnes.