ONC+ Developer's Guide

Passing Arbitrary Data Types

Data types passed to and received from remote procedures can be any of a set of predefined types, or can be programmer-defined types. RPC handles arbitrary data structures, regardless of the byte orders or structure layout conventions of different machines. RPC always converts these structures to a standard transfer format called external data representation (XDR) before sending them over the transport. The conversion from a machine representation to XDR is called serializing, and the reverse process is called deserializing.

The translator arguments of rpc_call() and rpc_reg() can specify an XDR primitive procedure, like xdr_u_int(), or a programmer-supplied routine that processes a complete argument structure. Argument processing routines must take only two arguments: a pointer to the result and a pointer to the XDR handle.

The XDR Primitive Type Routines are:

The fixed-width integer types found in int_types.h, the routines xdr_char(), xdr_short(), xdr_int(), and xdr_hyper() (and the unsigned versions of each) have equivalent functions with names familiar to ANSI C, as indicated in the following table:

Table 4–1 Primitive Type Equivalences

Function 

Equivalent 

xdr_char()

xdr_int8_t()

xdr_u_char()

xdr_u_int8_t()

xdr_short()

xdr_int16_t()

xdr_u_short()

xdr_u_int16_t()

xdr_int()

xdr_int32_t()

xdr_u_int()

xdr_u_int32_t()

xdr_hyper()

xdr_int64_t()

xdr_u_hyper()

xdr_u_int64_t()

The nonprimitive xdr_string(), which takes more than two parameters, is called from xdr_wrapstring().

The following example of a programmer-supplied routine contains the calling arguments of a procedure.

struct simple {
 	int a;
 	short b;
 } simple;

The XDR routine xdr_simple() translates the argument structure as shown in the following code example.


Example 4–3 xdr_simple Routine

#include <rpc/rpc.h>
#include "simple.h"
 
bool_t
xdr_simple(xdrsp, simplep)
	XDR *xdrsp;
	struct simple *simplep;
{
	if (!xdr_int(xdrsp, &simplep->a))
		return (FALSE);
	if (!xdr_short(xdrsp, &simplep->b))
		return (FALSE);
	return (TRUE);
}

rpcgen can automatically generate an equivalent routine.

An XDR routine returns nonzero (a C TRUE) if it completes successfully, and zero otherwise. A complete description of XDR is provided in Appendix C, XDR Protocol Specification.

The following list shows prefabricated routines:

For example, to send a variable-sized array of integers, the routine is packaged in a structure containing the array and its length:

struct varintarr {
 	int *data;
 	int arrlnth;
 } arr;

Translate the array with xdr_varintarr(), as shown in the following code example.


Example 4–4 xdr_varintarr Syntax Use

bool_t
xdr_varintarr(xdrsp, arrp)
	XDR *xdrsp;
	struct varintarr *arrp;
{
	return(xdr_array(xdrsp, (caddr_t)&arrp->data,
		(u_int *)&arrp->arrlnth, MAXLEN,
		sizeof(int), xdr_int));
}

The arguments of xdr_array() are the XDR handle, a pointer to the array, a pointer to the size of the array, the maximum array size, the size of each array element, and a pointer to the XDR routine to translate each array element. If the size of the array is known in advance, use xdr_vector(), as shown in the following code example.


Example 4–5 xdr_vector Syntax Use

int intarr[SIZE];

bool_t
xdr_intarr(xdrsp, intarr)
	XDR *xdrsp;
	int intarr[];
{
	return (xdr_vector(xdrsp, intarr, SIZE,
				sizeof(int),
xdr_int));
}

XDR converts quantities to 4-byte multiples when serializing. For arrays of characters, each character occupies 32 bits. xdr_bytes() packs characters. It has four parameters similar to the first four parameters of xdr_array().

Null-terminated strings are translated by xdr_string(), which is like xdr_bytes() with no length parameter. On serializing xdr_string() gets the string length from strlen(), and on deserializing it creates a null-terminated string.

The following example calls the built-in functions xdr_string() and xdr_reference(), which translates pointers to pass a string, and struct simple from previous examples.


Example 4–6 xdr_reference Syntax Use

struct finalexample {
	char *string;
	struct simple *simplep;
} finalexample;

bool_t
xdr_finalexample(xdrsp, finalp)
	XDR *xdrsp;
	struct finalexample *finalp;
{
	if (!xdr_string(xdrsp, &finalp->string,
			MAXSTRLEN))
		return (FALSE);
	if (!xdr_reference( xdrsp, &finalp->simplep,
			sizeof(struct simple), xdr_simple))
		return (FALSE);
	return (TRUE);

}

Note that xdr_simple() could have been called here instead of xdr_reference().