The Remote Procedure Call Language (RPCL) is identical to the eXternal Data Representation (XDR) language, except for the added program definition.
Because XDR data types are described in a formal language, procedures that operate on these data types must be described in a formal language. The RPCL, an extension to the XDR language, is used for this purpose.
RPC uses RPCL as the input language for its protocol and routines. RPCL specifies data types used by RPC and generates XDR routines that standardize representation of the types. To implement service protocols and routines, RPCL uses the rpcgen command to compile input in corresponding C language code.
RPC language descriptions include:
See "RPC Language ping Program Example" for more information. Also, see "Exceptions to the RPCL Rules" for instances where these rules do not apply.
An RPCL file consists of a series of definitions in the following format:
definition-list: definition ";" definition ";" definition-list
RPCL recognizes the following six types of definitions:
definition: enum-definition struct-definition union-definition typedef-definition const-definition program-definition
The C language structures are usually located in header files in either the /usr/include or /usr/include/sys directory, but they can be located in any directory in the file system. An XDR structure is declared almost exactly like its C language counterpart; for example:
struct-definition: "struct" struct-ident "{" declaration-list "}"
declaration-list: declaration ";" declaration ";" declaration-list
Compare the following XDR structure to a two-dimensional coordinate with the C structure that it is compiled into in the output header file.
struct coord { struct coord { int x; --> int x; int y; int y;
}; }; typedef struct coord coord;
Here, the output is identical to the input, except for the added typedef at the end of the output. As a result, the programmer can use coord instead of struct coord when declaring items.
XDR unions are discriminated unions and look different from C unions. XDR unions are more analogous to Pascal variant records than to C unions. Following is an XDR union definition:
union-definition: "union" union-ident "switch" "(" declaration ")" "{" case-list "}"
case-list: "case" value ":" declaration ";" "default" ":" declaration ";" "case" value ":" declaration ";" case-list
Following is an example of a type that might be returned as the result of a read data operation. If there is no error, the type returns a block of data; otherwise, it returns nothing.
union read_result switch (int errno) { case 0 opaque data[1024]; default: void; };
The type is compiled into the following structure:
struct read_result { int errno; union { char data[1024]; }read_result_u; }; typedef struct read_result read_result;
Note: The union component of this output structure is identical to the type, except for the trailing _u .
XDR enumerations have the same syntax as C enumerations.
enum-definition: "enum" enum-ident "{" enum-value-list "}"
enum-value-list: enum-value enum-value "," enum-value-list
enum-value: enum-value-ident enum-value-ident "=" value
Compare the following example of an XDR enumeration with the C enumeration it is compiled into.
enum colortype { enum colortype { RED = 0, RED = 0, GREEN = 1, --> GREEN = 1, BLUE = 2 BLUE = 2, }; }; typedef enum colortype colortype;
XDR type definitions (typedefs) have the same syntax as C typedefs.
typedef-definition: "typedef" declaration
The following example defines an fname_type used for declaring file-name strings with a maximum length of 255 characters.
typedef string fname_type<255>; --> typedef char *fname_type;
XDR constants can be used wherever an integer constant is required. The definition for a constant is:
const-definition: "const" const-ident "=" integer
For example, the following defines a constant DOZEN equal to 12 .
const DOZEN = 12; --> #define DOZEN 12
RPC programs are declared using the following syntax:
program-definition: "program" program-ident "{" version-list "}" "=" value
version-list: version ";" version ";" version-list
version: "version" version-ident "{" procedure-list "}" "=" value
procedure-list: procedure ";" procedure ";" procedure-list
procedure: type-ident procedure-ident "(" type-ident ")" "=" value
The time protocol is defined as follows:
/* * time.x: Get or set the time. Time is represented as number * of seconds since 0:00, January 1, 1970. */ program TIMEPROG { version TIMEVERS { unsigned int TIMEGET (void) = 1; void TIMESET (unsigned) = 2; } = 1; } = 44;
This file compiles into the following #define statements in the output header file:
#define TIMEPROG 44
#define TIMEVERS 1
#define TIMEGET 1
#define TIMESET 2
XDR includes four types of declarations: simple declarations, fixed-length array declarations, variable-length array declarations, and pointer declarations. These declarations have the following forms:
declaration: simple-declaration fixed-array-declaration variable-array-declaration pointer-declaration
Simple XDR declarations are like simple C declarations, as follows:
simple-declaration: type-ident variable-ident
An example of a simple declaration is:
colortype color; --> colortype color;
Fixed-length array declarations are like C array declarations, as follows:
fixed-array-declaration: type-ident variable-ident "[" value "]"
An example of a fixed-length array declaration is:
colortype palette[8]; --> colortype palette[8]
Variable-length array declarations have no explicit syntax in C, so XDR invents its own syntax using angle brackets. The maximum size is specified between the angle brackets. A specific size can be omitted to indicate that the array may be of any size.
variable-array-declaration: type-ident variable-ident "<" value ">" type-ident variable-ident "<" ">"
An example of a set of variable-length array declarations is:
int heights<12>; /* at most 12 items */ int widths<>; /* any number of items */
Note: The maximum size is specified between the angle brackets. The number, but not the angle brackets, may be omitted to indicate that the array can be of any size.
Since variable-length arrays have no explicit syntax in C, these declarations are actually compiled into structure definitions, signified by struct . For example, the heights declaration is compiled into the following structure:
struct { u_int heights_len; /* # of items in array */ int *heights_val; /* # pointer to array */ } heights;
Pointer declarations are made in XDR exactly as they are in C. The programmer cannot send pointers over a network, but can use XDR pointers for sending recursive data types such as lists and trees. In XDR language, the type is called optional-data , instead of pointer . Pointer declarations have the following form in XDR language:
pointer-declaration: type-ident "*" variable-ident
An example of a pointer declaration is:
listitem *next; --> listitem *next;
The RPCL has the following syntax requirements:
Exceptions to the RPC language rules include Booleans, strings, opaque data, and voids.
The C language has no built-in Boolean type. However, the RPC library uses a Boolean type called bool_t , which is either True or False. Objects that are declared as type bool in XDR language are compiled into bool_t in the output header file; for example:
bool married; --> bool_t married;
The C language has no built-in string type. Instead, it uses the null-terminated char * convention. In XDR language, strings are declared using the string keyword, and then compiled into char * in the output header file. The maximum size contained in the angle brackets specifies the maximum number of characters allowed in the strings (not counting the null character). The maximum size may be left off, indicating a string of arbitrary length.
Compare the following examples:
string name<32>; --> char *name;
string longname<>; --> char *longname;
Opaque data is used in RPC and XDR to describe untyped data, which consists of sequences of arbitrary bytes. Opaque data may be declared either as a fixed-length or variable-length array, as in the following examples:
opaque diskblock[512]; --> char diskblock[512];
opaque filedata<1024>; --> struct { u_int filedata_len; char *filedata_val; } filedata
In a void declaration, the variable is not named. The declaration is simply void . Void declarations can occur as the argument or result of a remote procedure in only two places: union definitions and program definitions.