Go to the previous, next section.
This document describes the abstract communication protocol that ILU uses when communicating between two modules that are written in different languages. It also describes the mapping of this protocol into various specific on-the-wire RPC protocols.
The ILU protocol is quite simple. Two types of messages are used, one to communicate parameters to a true method, and the other to communicate results and/or exceptions from the true method to surrogate caller. Parameters and values are encoded according to a simple abstract external data representation format. This abstract protocol identifies what information is passed between modules without specifying its exact mapping to bit patterns.
The first type of message is called a request. Each request consists of a code identifying the method being requested, an authentication block identifying the principal making the call, and a list of parameter inputs to the method being called. The method is identified by passing the one-based ordinal value (that is, the index of the method in the list of methods, beginning with one) of the method, in the list of methods as specified in the ISL description of the class which actually defines the method. No more than 65278 (1-0xFEFF) methods may be directly specified for any type (though more methods may be inherited by a type). Method codes 0xFF00 to 0xFFFF are reserved for ILU internal use. The principal is identified by a block of authentication credentials information which varies depending on the specific authentication protocol used. These credentials may be either in the request header, or may appear as a parameter of the request. (Note: There should also be an ILU protocol version number somewhere here, but there isn't (yet).)
The result message is used to convey return values and exception
values from the true method back to the caller. It consists of a Boolean
value, indicating whether the call was successful (for TRUE
) or
signalled an exception (for FALSE
). If successful, the return value (if any),
follows, followed by the values of any Out
parameters, in the order
they are specified as parameters. If an exception was signalled, a value
between 1 and 2^16-1 follows, indicating the ordinal value specific exception in
the list specified in the definition of the method, followed by a value of the
exception type, if any was specified for the exception.
Simple numerical values, of types integer
, cardinal
, real
, or byte
,
are passed directly.
Character
values are passed as integer values in the range [0,2^16-1].
Short character
values are passed as integer values in the range [0,2^16-1].
Long character
values are passed as integer values in the range [0,2^32-1].
Enumeration
values are passed as integer values in the range [0,2^16-1], the
value being the zero-based ordinal value of the corresponding enumeration value
in the original list of enumeration values in the definition of the enumerated type.
Boolean
values are passed as as integer values of either 0, for FALSE
, or 1, for TRUE
.
Optional
values are passed by first passing a Boolean value, with TRUE
indicating
that a non-NIL
value is being passed, and then only in the non-NIL
case
passing a value of the optional value's indicated type.
Sequence
values are passed by first passing a count,
as an integer in the range [0,2^32-1] for sequences without limits, or for sequences with
limits greater than 2^16-1, or an integer in the range [0,2^16-1], for sequences
with limits less than 2^16, indicating the number
of elements in the sequence, and then that number of values of the sequence's base
type.
Array
values are passed by passing a number of elements of the array's base type corresponding
to the size of the array.
Record
values are passed by passing values of types corresponding to the fields of the record, following the
order in which the fields are defined in the ISL definition of the record.
Union
values are passed by passing a value of the discriminant type, which indicates which branch
of the union constitutes the union's actual type, usually followed by a value of the union's actual type.
If the discriminant value indicates a branch of the union which has no associate value, only the
discriminant value is passed.
Object
values are passed in four different forms,
depending on whether or not the object value is in the discriminator position,
whether or not the object's type is a singleton
type, and
whether or not the object reference is NIL
.
singleton
type. In this case, the object is already known to both sides, and the object
is implicit; that is, no value is passed.
singleton
type. In this case,
the object ID (comprising the instance handle and the server ID) of the object is passed as a
sequence of short character
value.
sequence of short character
values: the first is
the unique ID of the most specific type of the object, and the second is the full string binding
handle of the object.
ILU depends on a reliable transport system to deliver messages. In particular, this means that a message is either delivered exactly once, or an error is signalled to the caller. (An unreliable transport mechanism based on UDP has also been implemented for use with Sun RPC. With this transport, messages may be delivered more than once. The ILU implementation of UDP on the server side filters out multiple receipts of the same request. Asynchronous methods may not be called over this transport mechanism, as reliable delivery of the request packet cannot be recognized by the client side. Non-asynchronous methods use the reply message as an acknowledgement that the request was received. Query: can requests be larger than the UDP packet size? How then are they segmented? Note: This should probably be replaced by a reliable UDP protocol, in which each message is acknowledged by the receiver. This would allow use of asynchronous methods over UDP. Of course, Sun RPC would not cooperate.)
ILU has no notion of "connections". That is, the called side has no pointer back to the caller, and no notion of how to do anything with the caller aside from returning a result message. Credentials passed in the request message can identify the caller, but not necessarily the location the call is made from. Protocols that need such information should pass it explicitly as an argument (an instance of a object type with methods defined on it) to the method.
This section describes the mapping of the abstract ILU protocol into the specific on-the-wire protocol used with Sun RPC(14). One of the major goals of this mapping is to preserve compatibility with existing Sun RPC services that can be described in ISL.
The request message used is that specified by the Sun RPC protocol. The
ILU method index is encoded as a 32-bit number in the "proc"
field in the Sun RPC request header. Principal identification is passed
in the "cred" field of the Sun RPC request header. By
default, ILU will pass the AUTH_UNIX
authentication
information, if no authentication method is specified for the method. For non-singleton
object types, the Sun RPC
program number passed in the "prog" slot is always 0x31000400, and the version
number passed in the "vers" slot is the CRC-32 hashed value of the ILU unique ID for
the object type. For singleton classes, the program number and version
specified in the singleton information is used.
The "mtype" field is set to CALL
. The indicated
"rpcvers" is 2. A monotonically increasing 32-bit serial number is
used in the "xid" field.
The reply message used is that specified by the Sun RPC protocol. The
"mtype" field is set to REPLY
. The "stat" field is always set
to MSG_ACCEPTED
. In the accepted_reply
, the authentication
verifier is always NULL. The "stat" field may be non-zero, to signal
one of a small number of "standard" exceptions, or may be zero. This
header is then followed by one of three forms: If a "standard"
exception was raised, nothing. If the method has no exceptions, the
return values and out parameters (if any). If the method has any
exceptions defined, a 32-bit value which specifies either successful
completion (a value of 0), or an exception (a value greater than 0,
which is the ordinal value of the particular exception being signalled
in the list of exceptions specified for this method), followed by either
the return value and out parameters (if any), in the case of successful
completion, or the exception value (if any), in the case of an
exception.
The mapping of ILU types into Sun RPC types is accomplished primarily by using the appropriate XDR (15) representation for that type.
Short integer
and integer
types are represented with the XDR Integer type. Long integer
types are represented as an XDR Hyper Integer.
Short cardinal
, byte
, and cardinal
types are represented
with the XDR Unsigned Integer type. Long cardinal
types are represented as an XDR Unsigned Hyper Integer.
Short real
numbers are encoded as XDR Floating-point. Real
numbers are encoded
as XDR Double-precision Floating-point. Long real
numbers are encoded as XDR Fixed-length
Opaque data of length 16.
Array
values are encoded as XDR Fixed-length Array, except for two special cases.
If the array is multi-dimensional,
it is encoded as a flat rendering into a single-dimensional array in row-major order (the last specified
index varying most rapidly). If the array is of element-type byte
or short character
, it is encoded
as an array of one (in the one-dimensional case) or more (in the greater-than-one dimensional case)
values of XDR Opaque Data.
Record
values are encoded as XDR Structures.
Union
values are encoded as XDR Discriminated Unions, with a discriminant of type
"unsigned int" containing the ILU short cardinal
discriminant.
Enumeration
values are encoded as XDR Unsigned Integer (note that this is different
from XDR Enumerations, which are encoded as XDR Integer).
Boolean
values are encoded as XDR Unsigned Integer, using the value 0 for FALSE
and the value 1 for TRUE
.
Sequence
values are encoded as XDR Variable-length Arrays, except for several special cases.
Sequences of short character
are encoded as XDR String, sequences of byte
are encoded
as XDR Variable-length Opaque Data, and sequences of character
are encoded as XDR String,
where the string is the UTF-2 encoding of the Unicode characters in the sequence.
Optional
values are encoded as an XDR Boolean value, followed by another encoded
value, if the Boolean value is TRUE.
Instances of an object
type are encoded as either zero (in the case of a method discriminant of a singleton type),
or one (in the case of a non-singleton discriminant, the object ID) or two (in the case
of a non-discriminant, the most-specific-type unique ID and the string binding handle) values
of type XDR String.
This section describes the mapping of the abstract ILU protocol into the specific on-the-wire protocol used with Xerox Courier(16). One of the major goals of this mapping is to preserve compatibility with existing Xerox Courier services that can be described in ISL. Unfortunately, many if not most important Courier services use bulk data transfer, something that is still only planned for ILU.
The request message used is the CallMessageBody
specified in section 4.3.1 of the Courier protocol.
A monotonically increasing 16-bit serial number is passed in the transactionID
field; a 32-bit number
drawn from a registry of (ILU type ID, Courier program number, Courier version) triples
is passed in the programNumber
field; a 16-bit version drawn from the same
registry is passed in the versionNumber
field; the ILU method index
is passed as a 16-bit value in the procedureValue
field.
Successful replies are sent using the Courier ReturnMessageBody
specified in section 4.3.3
of the Courier specification. The procedureResults
field contains
the return value, if any, followed by the INOUT
and OUT
parameter values, if any.
User exceptions are signalled using the AbortMessageBody
specified in section 4.3.4
of the Courier specification. The errorValue
field contains a value greater than 0,
which is the ordinal value of the particular exception being signalled
in the list of exceptions specified for this method. The errorArguments
field
contain the exception value, if any.
System exceptions (of exception type ilu.ProtocolError
) are signalled
using the RejectMessageBody
message of section 4.3.2. The rejectionDetail
field of the message contains the ProtocolError
detail.
The mapping of ILU types into Courier types is accomplished primarily by using the appropriate Courier Layer 2 representation for that type.
Short integer
and integer
types are represented with the Courier Integer
and Long Integer
types.
Long integer
types are represented as an integer
followed by a cardinal
.
Short cardinal
, byte
, and cardinal
types are
represented with the Courier cardinal
, cardinal
,
and long cardinal
types, respectively. Long cardinal
types
are represented as a big-endian (most significant 16 bits first) Courier array of 4 cardinal
s.
As the Courier protocol does not have any mapping for floating point values,
short real
numbers are passed as a Courier long cardinal
,
real
numbers are encoded as a big-endian array of two Courier long cardinal
values,
and long real
numbers are encoded as big-endian array of four Courier long cardinal
values.
Array
values are encoded as Courier one-dimensional
array
s. If the array is multi-dimensional, it is encoded as a
flat rendering into a single-dimensional array in row-major order (the
last specified index varying most rapidly). If the array is of type
byte
or short character
, the contents of the ILU
value are packed into a Courier array of unspecified
two values per array
element, so that the Courier array is half the length of the actual ILU array.
Record
values are encoded as Courier record
values.
Union
values of union types whose discriminant type can be mapped to a 16-bit value type in
the range [0,2^16-1] are passed as Courier choice
values. Other
unions are passed as a Courier long cardinal
, followed by the
value of the union's indicated type (if any).
Enumeration
values are encoded as Courier enumeration
values.
Boolean
values are encoded as Courier boolean
values.
Sequence
values are encoded as Courier sequence
s, except for several special cases.
Sequences of N short character
s or byte
s are encoded as
either a Courier cardinal
, for sequences with limits less than 2^16, or long cardinal
,
for sequences with no limits or limits greater than 2^16-1, value of N, followed by
(N+1)/2
values of Courier unspecified
, each such value
containing two short character
or byte
values, packed in big-endian order.
Optional
values are encoded as an Courier boolean
value, followed by another encoded
value, if the Boolean value is TRUE
.
Instances of an object
type are encoded as either zero (in the case of a method discriminant of a singleton type),
or one (in the case of a non-singleton discriminant, the object ID) or two (in the case
of a non-discriminant, the most-specific-type unique ID and the string binding handle) values
of ISL short sequence of short character
. CORBA Nil object references are represented as two
zero-length short sequence of short character
s.
Go to the previous, next section.