XEROX	RPC
2

4

1

RPC
1

4

By:  Henry Thompson (HThompson.pa@Xerox.com)
Internal

The Remote Procedure Call package

File: rpc.tedit
Revised: December 6, 1985
Uses: RPC*, Lupine
Remote Procedure Calls
This package implements the Cedar RPC transport mechanism.  Its architecture is copied more or less directly from the Cedar implementation, to which reference should be made in difficulty.  It is designed to be used in conjunction with stubs produced by the Interlisp-D version of Lupine (see below) to provide remote service.
As it implements not only remote procedure calls, but also remote signalling a la CedarMesa, it depends on the Signals package - SIGNAL, q.v. for more information.
To start the RPC world, call InitRPC() - to turn it off, use StopRPC().
LUPINE - Producing stubs
The goal of all this is to allow an Interlisp-D system to export services to or import services from remote machines.  The file <lispusers>rpc-lupine.dcom implements a stub creation mechanism modeled on the Cedar version (ref. Bruce Nelson's thesis (Xerox PARC report CSL-81-9) and the Lupine User's Guide - [indigo]<cedar6.0>documentation>LupineUsersGuide.press.).  In particular the function Lupine(packageName functionSpecList signalSpecList  typeSpecList lupineTypeString noServer noClient) will produce a set of server stubs to interface between the RPC transport mechanisms and a set of vanilla Lisp functions, and a set of client stubs to communicate between callers of those functions and the RPC transport mechanism.  This allows the network to intervene between the caller and the callee.  
The crucial point to comprehend in the RPC world is that the semantics of a remote call are the same as the semantics of a local call - all the effort is directed at hiding the fact that anything out of the ordinary is going on - pay no attention to the man behind the curtain.
A trivial example will demonstrate the basic story - suppose we have the following Cedar interface spec:
Trivial: DEFINITIONS =

BEGIN
Triv: TYPE = RECORD[a,b: INTEGER];

Trivial: PROC[arg1: INT, arg2: Rope.ROPE, arg3: Triv] RETURNS[result: BOOLEAN];

TrivialFailure: TYPE = { badNum, badString };

TrivialFailed: SIGNAL[why: TrivialFailure];

END.
Translating this with Cedar Lupine will produce client and server interfaces to the RPC transport mechanisms.  To plug into those from Lisp, or to plug Lisp to Lisp, we must supply the same information as is contained in the Cedar interface spec. to Lisp.  The following records from Lisp Lupine are used to specify an interface:
(RECORD FunctionSpec (fn . specs))
(RECORD ArgSpec (argName argType))
(RECORD TypeSpec (typeName typeType))
(RECORD LupineType (typeName . typeParm))
The following are the equivalent for Lisp Lupine of the above interface spec:
(RPAQQ TrivialSpec (
	(Trivial (arg1 FIXP)(arg2 STRING)(arg3 Triv)(RETURNS BOOLEAN)))
(RPAQQ TrivialSignals (
	(TrivialFailed (ARGS TrivialFaulure)))
(RPAQQ TrivialTypes (
   (Triv (RECORD (a SSMALLP)(b SSMALLP))
   (TrivialFailure (ENUMERATION badNum badString)))
Nearly the same format is used for both functions and signals, since signals are just functions by another name. The semantics of signals are described in <lispusers>signal.tedit, press.
Types, which appear in the argType and typeType fields above, are either atomic or of the form given by LupineType, in which case the name is atomic, and the parameters are particular to the named type.  Only some primative types take parameters - user-defined types cannot, although of course they can be defined as parameterised types, as in the above example.
The built-in types available are {SSMALLP FIXP BOOLEAN STRING ATOM STREAM ENUMERATION ARB BITS LIST RECORD RESULT SIGARGS REF SEQRECORD SEQUENCE}.  Of these SSMALLP, FIXP, BOOLEAN, STRING, ATOM and ARB are atomic.  STREAM, ENUMERATION, BITS, LIST, RECORD, REF, SEQRECORD, and SEQUENCE are parameterised.  RESULT and SIGARGS are parameterised pseudo-types, described below.  The following table describes each built-in type in turn, giving its semantics and the corresponding Cedar type, if any.
Lisp		Cedar	Parameter	Semantics
SSMALLP	INTEGER		small numbers in the range -215 - 215-1
FIXP		INT			numbers in the range -231 - 231-1
BOOLEAN	BOOLEAN		NIL/non-NIL  <-> FALSE/TRUE
STRING	Rope.ROPE		"random character strings"
ATOM		ATOM			uniqueIdentifer  <-> $uniqueIdentifier
ARB		Rope.ROPE		The escape type - it uses READ and PRINT to move an arbitrary printable Lisp object (Only between Lisp and Lisp - Cedar wouldn't know what to do if it saw one)
STREAM	Rope.ROPE		(<filename>)	Like a string, but goes directly into a stream, which may or may not already be open, and will be handed back open.
ENUMERATION	{a, b, c}		(a b c)	Small cardinal numbers treated as named elements.  On the lisp side atoms, on the cedar side the elements of the type.
BITS		[0..n]		(m)	m bit field with a small number in it.  CARDINAL is pre-declared as a synonym for (BITS 16) and LONGCARDINAL for (BITS 32).
LIST		LIST OF		(<type>)	A list of elements of type <type>
REF		REF			(<type>)	Basically a no-op in Lisp, except wrt SEQRECORDs, q.v.
RECORD	RECORD		(<field>+)	Cannot appear directly in an arg spec - must be declared as a type and used by name.  Each field gives a name and a type.  The fields must correspond to the fields of an actual Lisp record of some kind.
SEQRECORD	RECORD		(<field>+)	As RECORD, but must have SEQUENCE as its last field.
SEQUENCE	SEQUENCE		(<type>)	Fixed length sequence of elements of type <type>
RESULT				(<field>+)	Used to specify the types of compound returned values.  Each field gives a name and a type.  The fields must correspond to the fields of an actual Lisp record of some kind, so that e.g. an instance of of it can be created to hand over the result of a call.
SIGARGS		(<field>+)	As RESULT, but to deal with the fact that in Lisp signals have only one argument, which may be compound.
The syntax of the spec is confused slightly by the necessity for distinguishing single from multiple return values, and atomic from compound arguments to signals.  The type of such things is coded by special values in the argName field of a spec, RETURNS for the return value and ARGS for the signal arguments.  These specs may either have a single typed parameter, or name a compound type of the sort RESULT or SIGARGS respectively, which in turn list the sub-components.
There is a simple example supplied in the file RPC-EXAMPLE. After it is loaded, If we call (Lupine 'RPC-Example SimpleSpec SimpleSignals  SimpleTypes "magic-string") we will get back the names of a pair of filecoms for all the necessary stubs etc.  The magic-string will be used as a default in the process of matching server and client at the time of initial connection.  If you want to allow it to default to the same value as the default generated by Cedar Lupine, you can read it out of the file SimpleRpcClientImpl.mesa, at the point in the definition of ImportInterface where it says:
type:  IF ~IsNull[type]
	THEN type ELSE "magic-string",
To actually export the interface so that clients can call you, you must call e.g. ExportRPC-Example(<type> <instance> <version> <user> <password>), where the user and password are required if the instance name you give is an rName.  The user must be the owner of the rName, and the password must be either a Grapevine key, or a Lisp-internal password, as from \INTERNAL/GETPASSWORD.  Likewise to import an interface exported by someone else, use e.g. ImportRPC-Example(<type> <instance> <version>).  See the forthcoming Cedar RPC documentation for a discussion of all the options with respect to establishing connections.  In brief the <type> argument names the service provided or required, and the <instance> argument names the machine which is (expected) to provide it.  For simple applications use a mnemonic string for <type> or let it default, and use a string or atom name for the machine.  Note that on nameless machines this should be (PORTSTRING(ETHERHOSTNUMBER)).  On import, <instance>=BROADCAST will find any server of the given <type> on the local (net 0) net.  The <version> argument is always optional, defaulting to something which will match all versions.  If provided it must be a CONS-pair of the form (lowest . highest), where <lowest> is the lowest numbered version you support/can talk to, and <highest> the highest.
A complete example is the easiest way to understand how all this works.  RPC-EXAMPLE and RPC-EXAMPLEUSER are the basis for such an example.  The functions in RPC-EXAMPLEUSER call the functions in RPC-EXAMPLE.  RPC-EXAMPLE contains the necessary arguments for Lupine.  RPC-EXAMPLECLIENT and RPC-EXAMPLESERVER contain the stubs generated by Lupine.  RPC-EXAMPLECLIENT and RPC-EXAMPLEUSER would be loaded into one machine, and RPC-EXAMPLE and RPC-EXAMPLESERVER into another.   RPC-EXAMPLE-CEDAR.DF is a directory of all the Cedar files needed to make up the equivalent server and/or client in Cedar.
Multiple connections/Symmetric connections
If you wish to communicate via a particular interface with more than one other host, you can call ImportXxx once for each host.  The result of ImportXxx is a handle you can supply to subsequent calls through the interface to identify the particular server you want to address the call to:
(SETQ h1 (ImportRPC-Example NIL "Host1"]
(SETQ h2 (ImportRPC-Example NIL "Host2"]
(Simple 3 "abc" h1)  will call the server on Host1,
(Simple 3 "abc" h2)  will call the server on Host2.
This n+1st argument defaults to the most recently imported interface for the package.  Handles can be supplied to UnimportXxx to remove a host from use - if no argument is supplied all interfaces are closed.
The story above about the names of stubs is slightly simplified.  To protect against name conflicts and allow a single machine to be both server and client, various name changes and MOVDs are done behind the scenes.  The default is that the client stub will be called e.g. "Simple", but the actually implementing function on the server side will be moved to Hidden.Simple, which is what the server stub will call.  To prevent this, answer No to the query when the server stubs are loaded.  In a parallel fashion, the client stubs are actually initially generated with  GENSYMed names, e.g. RPCClientStub.Simple to avoid redefining the original functions, and moved into place on loading.  The following examples should make this all clear:
Making the stubs and running.
_(LOAD 'RPC-EXAMPLE)	Get the functions and the specs
_(Lupine 'RPC-Example SimpleSpec SimpleSignals SimpleTypes)	Create the stubs
_(CLEANUP RPC-EXAMPLECLIENT RPC-EXAMPLESERVER)	Save the results
To test running server and client on this machine:
_(HideRPC-ExampleServerMovds)	Hide the server
_(MovdsForRPC-Example)	Install the client
_(ExportRPC-Example NIL (ETHERHOSTNAME))	ThisMachine is now a server
_(SETQ SomeMachineHandle (ImportRPC-Example NIL (ETHERHOSTNAME)))
Starting a server from scratch
_(LOAD 'RPC-EXAMPLE.DCOM)
_(LOAD 'RPC-EXAMPLESERVER.DCOM)	the order of loading is important
Hide server fns (must have been already loaded)? 	Yes or no, as appropriate -
	if you are going to be  a client as well you must say yes.
_(ExportRPC-Example NIL (ETHERHOSTNAME))	This machine is now a server
Starting a client from scratch  (if both then this follows setup as server)
_(LOAD 'RPC-EXAMPLECLIENT.DCOM)
_(SETQ SomeMachineHandle (ImportRPC-Example NIL "NameOfServer"))	Server here
	must have exported or this will time out or fail.
Secure communication
You can choose to have any of your remote calls encrypted for security by passing as the n+2nd argument to any call the result of calling StartConversation(caller key callee 'cbcCheck), which creates a Conversation and uses it to establish a secure channel with your server.  caller and key are the sorts of things which \INTERNAL/GETPASSWORD returns, and callee is  an RName for the 'owner' of the server.
EVAL server
There is an RPC-based EVAL server and client contained in RPCEVAL.DCOM, RPCEVALSERVER.DCOM and RPCEVALCLIENT.DCOM. To use it, follow the standard procedure, as follows. To set up a server:
_(LOAD 'RPCEVAL.DCOM)
_(LOAD 'RPCEVALSERVER.DCOM)
_(ExportRPCEval NIL (ETHERHOSTNAME))
To set up a client :
_(LOAD 'RPCEVALCLIENT.DCOM)
_(SETQ handle (ImportRPCEval NIL "NameOfServer"))
To invoke the remote server, call 
(RPCEval <form> handle) or (RPCApply <function> <args> handle)
where handle defaults to the last one imported, if not supplied.

�����(LIST ((PAGE NIL (PAPERSIZE Letter FOLIOINFO (ARABIC  )) (0 0 612 792) ((FOLIO NIL (PARALOOKS (QUAD CENTERED) CHARLOOKS (SUPERSCRIPT 0 INVISIBLE OFF SELECTPOINT OFF PROTECTED OFF SIZE 10 FAMILY MODERN OVERLINE OFF STRIKEOUT OFF UNDERLINE OFF EXPANSION REGULAR SLOPE REGULAR WEIGHT MEDIUM INVERTED OFF USERINFO NIL STYLE NIL) FORMATINFO (ARABIC  )) (174 36 288 36) NIL) (HEADING NIL (HEADINGTYPE RUNNINGHEAD) (84 744 528 36) NIL) (TEXT NIL NIL (84 96 456 600) NIL))) (PAGE NIL (PAPERSIZE Letter FOLIOINFO (ARABIC  )) (0 0 612 792) ((FOLIO NIL (PARALOOKS (QUAD CENTERED) CHARLOOKS (SUPERSCRIPT 0 INVISIBLE OFF SELECTPOINT OFF PROTECTED OFF SIZE 10 FAMILY MODERN OVERLINE OFF STRIKEOUT OFF UNDERLINE OFF EXPANSION REGULAR SLOPE REGULAR WEIGHT MEDIUM INVERTED OFF USERINFO NIL STYLE NIL) FORMATINFO (ARABIC  )) (174 36 288 36) NIL) (HEADING NIL (HEADINGTYPE RUNNINGHEAD) (84 744 528 36) NIL) (TEXT NIL NIL (84 96 456 600) NIL))) (PAGE NIL (PAPERSIZE Letter FOLIOINFO (ARABIC  )) (0 0 612 792) ((FOLIO NIL (PARALOOKS (QUAD CENTERED) CHARLOOKS (SUPERSCRIPT 0 INVISIBLE OFF SELECTPOINT OFF PROTECTED OFF SIZE 10 FAMILY MODERN OVERLINE OFF STRIKEOUT OFF UNDERLINE OFF EXPANSION REGULAR SLOPE REGULAR WEIGHT MEDIUM INVERTED OFF USERINFO NIL STYLE NIL) FORMATINFO (ARABIC  )) (174 36 288 36) NIL) (HEADING NIL (HEADINGTYPE RUNNINGHEAD) (84 744 528 36) NIL) (TEXT NIL NIL (84 96 456 600) NIL)))))�������(����È�����������������������������(����È�����������������������������(�Š�Š8�����������������������������(�Š�Š8������������������������������D����È��������È�������PAGEHEADING�RUNNINGHEAD���������������4���������������`��À��������������������������+����Ø�������������������������������+����Ø�������������������������������������
��MODERN�
���������TERMINAL�
���������TERMINAL�
����������MODERN�
������€��MODERN�
���������MODERN����������MODERN�����������LOGO�����������MODERN�
����������	HELVETICA�
���������GACHA�
����������	HELVETICA�
����������	HELVETICA�
����������������������������������	�����������HRULE.GETFN��MODERN�
���������������	�����������HRULE.GETFN��MODERN�
���������������	�����������HRULE.GETFN��MODERN�
���������������	������������������������HRULE.GETFN��MODERN��������������������������HRULE.GETFN��MODERN������������������������-����	���������	����	�������������
���������!�����������	�������������	���������=����	��������������������	��������G����	���������¤����	���������H����	��������������������	��������!����	������������	���������i����	����������������������Ö������������J����	���������•�����������	���������N����	����������������������������»����	��������k����	��������ï����	��������� �������������.�����������������������������������������#�����������������������������������������-�������������-�������������4�������������°�������������“�������������–�������������Ž�������������:�������������K���������������������������Í���������������������������7�������������M�����������������������������������������������������k������������Ù����	��������O����	���������8������������<����	��������U����	���������*�����������	��������!����	���������)�������������)�������������4�������������4�������������Ð����	��������ä����	��������������������	���������������������������	����������������;������������������	����������������.������������������	���������2����	�������
���������������������������	����������������������������������	����������������(������������������	����������������A��������������������������������������������������������������������������"����	���������2����	��������������	���������;����	����������������(������������������	������������������������������+����	������������������������������������@������������������	�������������
���0�����������	��������������������	��������—����	��������������������	���������½����	�������������	�������������	���������%����	�������������	�������������	���������2����	���������#����	���������?�������������@����	����������������������0¶zº