|
|
1.1 root 1: .EQ
2: delim $$
3: .EN
4: .OH 'XDR Protocol Spec''Page \\\\n(PN'
5: .EH 'Page \\\\n(PN''XDR Protocol Spec'
6: .OF 'Sun Microsystems''Release 2.0'
7: .EF 'Release 2.0''Sun Microsystems'
8: .RP
9: .rm DY
10: .TL
11: .ps 20
12: External Data Representation
13: .sp.5
14: Protocol Specification
15: .
16: .H 1 "Introduction"
17: .LP
18: This manual describes library routines that allow a C programmer to
19: describe arbitrary data structures in a machine-independent fashion.
20: The eXternal Data Representation (XDR) standard
21: is the backbone of Sun's Remote Procedure Call package,
22: in the sense that data for remote procedure calls
23: is transmitted using the standard.
24: XDR library routines should be used to transmit data
25: that is accessed (read or written) by more than one type of machine.
26: .LP
27: This manual contains a description of XDR library routines,
28: a guide to accessing currently available XDR streams,
29: information on defining new streams and data types,
30: and a formal definition of the XDR standard.
31: XDR was designed to work across different languages,
32: operating systems, and machine architectures.
33: Most users (particularly RPC users)
34: only need the information in sections 2 and 3 of this document.
35: Programmers wishing to implement RPC and XDR on new machines
36: will need the information in sections 4 through 6.
37: Advanced topics, not necessary for all implementations,
38: are covered in section 7.
39: .LP
40: On Sun systems,
41: C programs that want to use XDR routines
42: must include the file
43: .L <rpc/rpc.h> ,
44: which contains all the necessary interfaces to the XDR system.
45: Since the C library
46: .L libc.a
47: contains all the XDR routines,
48: compile as normal.
49: .LS
50: cc \fIprogram.c\fP
51: .LE
52: .
53: .H 1 "Justification"
54: .LP
55: Consider the following two programs,
56: .L writer :
57: .LS
58: #include <stdio.h>
59: .sp.5
60: main() /* writer.c */
61: {
62: long i;
63: .sp.5
64: for (i = 0; i < 8; i++) {
65: if (fwrite((char *)&i, sizeof(i), 1, stdout) != 1) {
66: fprintf(stderr, "failed!\en");
67: exit(1);
68: }
69: }
70: }
71: .LE
72: and
73: .L reader :
74: .LS
75: #include <stdio.h>
76: .sp.5
77: main() /* reader.c */
78: {
79: long i, j;
80: .sp.5
81: for (j = 0; j < 8; j++) {
82: if (fread((char *)&i, sizeof (i), 1, stdin) != 1) {
83: fprintf(stderr, "failed!\en");
84: exit(1);
85: }
86: printf("%ld ", i);
87: }
88: printf("\en");
89: }
90: .LE
91: The two programs appear to be portable, because
92: (a) they pass
93: .L lint
94: checking, and
95: (b) they exhibit the same behavior when executed
96: on two different hardware architectures, a Sun and a VAX.
97: .LP
98: Piping the output of the
99: .L writer
100: program to the
101: .L reader
102: program gives identical results on a Sun or a VAX.\(dd
103: .FS
104: \(dd VAX is a trademark of Digital Equipment Corporation.
105: .FE
106: .LS
107: sun% writer | reader
108: 0 1 2 3 4 5 6 7
109: sun%
110: ---
111: vax% writer | reader
112: 0 1 2 3 4 5 6 7
113: vax%
114: .LE
115: With the advent of local area networks and Berkeley's 4.2 BSD
116: .UX
117: came the concept of ``network pipes'' \(em
118: a process produces data on one machine,
119: and a second process consumes data on another machine.
120: A network pipe can be constructed with
121: .L writer
122: and
123: .L reader .
124: Here are the results if the first produces data on a Sun,
125: and the second consumes data on a VAX.
126: .LS
127: sun% writer | rsh vax reader
128: 0 16777216 33554432 50331648 67108864 83886080 100663296 117440512
129: sun%
130: .LE
131: Identical results can be obtained by executing
132: .L writer
133: on the VAX and
134: .L reader
135: on the Sun.
136: These results occur because the byte ordering
137: of long integers differs between the VAX and the Sun,
138: even though word size is the same.
139: Note that 16777216 is $ 2 sup 24 $ \(em
140: when four bytes are reversed, the 1 winds up in the 24th bit.
141: .LP
142: Whenever data is shared by two or more machine types,
143: there is a need for portable data.
144: Programs can be made data-portable by replacing the
145: .L read()
146: and
147: .L write()
148: calls with calls to an XDR library routine
149: .L xdr_long() ,
150: a filter that knows the standard representation
151: of a long integer in its external form.
152: Here are the revised versions of
153: .L writer :
154: .LS
155: #include <stdio.h>
156: #include <rpc/rpc.h> /* xdr is a sub-library of the rpc library */
157: .sp.5
158: main() /* writer.c */
159: {
160: XDR xdrs;
161: long i;
162: .sp.5
163: xdrstdio_create(&xdrs, stdout, XDR_ENCODE);
164: for (i = 0; i < 8; i++) {
165: if (! xdr_long(&xdrs, &i)) {
166: fprintf(stderr, "failed!\en");
167: exit(1);
168: }
169: }
170: }
171: .LE
172: and
173: .L reader :
174: .LS
175: #include <stdio.h>
176: #include <rpc/rpc.h> /* xdr is a sub-library of the rpc library */
177: .sp.5
178: main() /* reader.c */
179: {
180: XDR xdrs;
181: long i, j;
182: .sp.5
183: xdrstdio_create(&xdrs, stdin, XDR_DECODE);
184: for (j = 0; j < 8; j++) {
185: if (! xdr_long(&xdrs, &i)) {
186: fprintf(stderr, "failed!\en");
187: exit(1);
188: }
189: printf("%ld ", i);
190: }
191: printf("\en");
192: }
193: .LE
194: The new programs were executed on a Sun,
195: on a VAX, and from a Sun to a VAX;
196: the results are shown below.
197: .LS
198: sun% writer | reader
199: 0 1 2 3 4 5 6 7
200: sun%
201: ---
202: vax% writer | reader
203: 0 1 2 3 4 5 6 7
204: vax%
205: ---
206: sun% writer | rsh vax reader
207: 0 1 2 3 4 5 6 7
208: sun%
209: .LE
210: Dealing with integers is just the tip of the portable-data iceberg.
211: Arbitrary data structures present portability problems,
212: particularly with respect to alignment and pointers.
213: Alignment on word boundaries may cause the
214: size of a structure to vary from machine to machine.
215: Pointers are convenient to use,
216: but have no meaning outside the machine where they are defined.
217: .LP
218: The XDR library package solves data portability problems.
219: It allows you to write and read arbitrary C constructs
220: in a consistent, specified, well-documented manner.
221: Thus, it makes sense to use the library even when the data
222: is not shared among machines on a network.
223: .LP
224: The XDR library has filter routines for
225: strings (null-terminated arrays of bytes),
226: structures, unions, and arrays, to name a few.
227: Using more primitive routines,
228: you can write your own specific XDR routines
229: to describe arbitrary data structures,
230: including elements of arrays, arms of unions,
231: or objects pointed at from other structures.
232: The structures themselves may contain arrays of arbitrary elements,
233: or pointers to other structures.
234: .LP
235: Let's examine the two programs more closely.
236: There is a family of XDR stream creation routines
237: in which each member treats the stream of bits differently.
238: In our example, data is manipulated using standard I/O routines,
239: so we use
240: .L xdrstdio_create() .
241: The parameters to XDR stream creation routines
242: vary according to their function.
243: In our example,
244: .L xdrstdio_create()
245: takes a pointer to an XDR structure that it initializes,
246: a pointer to a FILE that the input or output is performed on,
247: and the operation.
248: The operation may be XDR_ENCODE for serializing in the
249: .L writer
250: program, or XDR_DECODE for deserializing in the
251: .L reader
252: program.
253: .LP
254: Note: RPC clients never need to create XDR streams;
255: the RPC system itself creates these streams,
256: which are then passed to the clients.
257: .LP
258: The
259: .L xdr_long()
260: primitive is characteristic of most XDR library
261: primitives and all client XDR routines.
262: First, the routine returns FALSE (0) if it fails,
263: and TRUE (1) if it succeeds.
264: Second, for each data type,
265: .L xxx ,
266: there is an associated XDR routine of the form:
267: .LS
268: xdr_xxx(xdrs, fp)
269: XDR *xdrs;
270: xxx *fp;
271: {
272: }
273: .LE
274: In our case,
275: .L xxx
276: is long, and the corresponding XDR routine is
277: a primitive,
278: .L xdr_long .
279: The client could also define an arbitrary structure
280: .L xxx
281: in which case the client would also supply the routine
282: .L xdr_xxx ,
283: describing each field by calling XDR routines
284: of the appropriate type.
285: In all cases the first parameter,
286: .L xdrs
287: can be treated as an opaque handle,
288: and passed to the primitive routines.
289: .LP
290: XDR routines are direction independent;
291: that is, the same routines are called to serialize or deserialize data.
292: This feature is critical to software engineering of portable data.
293: The idea is to call the same routine for either operation \(em
294: this almost guarantees that serialized data can also be deserialized.
295: One routine is used by both producer and consumer of networked data.
296: This is implemented by always passing the address
297: of an object rather than the object itself \(em
298: only in the case of deserialization is the object modified.
299: This feature is not shown in our trivial example,
300: but its value becomes obvious when nontrivial data structures
301: are passed among machines.
302: If needed, you can obtain the direction of the XDR operation.
303: See section 3.7 for details.
304: .LP
305: Let's look at a slightly more complicated example.
306: Assume that a person's gross assets and liabilities
307: are to be exchanged among processes.
308: Also assume that these values are important enough
309: to warrant their own data type:
310: .LS
311: struct gnumbers {
312: long g_assets;
313: long g_liabilities;
314: };
315: .LE
316: The corresponding XDR routine describing this structure would be:
317: .LS
318: bool_t /* TRUE is success, FALSE is failure */
319: xdr_gnumbers(xdrs, gp)
320: XDR *xdrs;
321: struct gnumbers *gp;
322: {
323: if (xdr_long(xdrs, &gp->g_assets) &&
324: xdr_long(xdrs, &gp->g_liabilities))
325: return(TRUE);
326: return(FALSE);
327: }
328: .LE
329: Note that the parameter
330: .L xdrs
331: is never inspected or modified;
332: it is only passed on to the subcomponent routines.
333: It is imperative to inspect the return value of each XDR routine call,
334: and to give up immediately and return FALSE if the subroutine fails.
335: .LP
336: This example also shows that the type
337: .L bool_t
338: is declared as an integer whose only values are TRUE (1) and FALSE (0).
339: This document uses the following definitions:
340: .LS
341: #define bool_t int
342: #define TRUE 1
343: #define FALSE 0
344: .sp.5
345: #define enum_t int /* enum_t's are used for generic enum's */
346: .LE
347: .LP
348: Keeping these conventions in mind,
349: .L xdr_gnumbers()
350: can be rewritten as follows:
351: .LS
352: xdr_gnumbers(xdrs, gp)
353: XDR *xdrs;
354: struct gnumbers *gp;
355: {
356: return (xdr_long(xdrs, &gp->g_assets) &&
357: xdr_long(xdrs, &gp->g_liabilities));
358: }
359: .LE
360: This document uses both coding styles.
361: .bp
362: .
363: .H 1 "XDR Library Primitives"
364: .LP
365: This section gives a synopsis of each XDR primitive.
366: It starts with basic data types and moves on to constructed data types.
367: Finally, XDR utilities are discussed.
368: The interface to these primitives
369: and utilities is defined in the include file
370: .L <rpc/xdr.h> ,
371: automatically included by
372: .L <rpc/rpc.h> .
373: .
374: .H 2 "Number Filters"
375: .LP
376: The XDR library provides primitives that translate between C numbers
377: and their corresponding external representations.
378: The primitives cover the set of numbers in:
379: .EQ
380: [signed, unsigned] * [short, int, long]
381: .EN
382: Specifically, the six primitives are:
383: .LS
384: bool_t xdr_int(xdrs, ip)
385: XDR *xdrs;
386: int *ip;
387: .sp.5
388: bool_t xdr_u_int(xdrs, up)
389: XDR *xdrs;
390: unsigned *up;
391: .sp.5
392: bool_t xdr_long(xdrs, lip)
393: XDR *xdrs;
394: long *lip;
395: .sp.5
396: bool_t xdr_u_long(xdrs, lup)
397: XDR *xdrs;
398: u_long *lup;
399: .sp.5
400: bool_t xdr_short(xdrs, sip)
401: XDR *xdrs;
402: short *sip;
403: .sp.5
404: bool_t xdr_u_short(xdrs, sup)
405: XDR *xdrs;
406: u_short *sup;
407: .LE
408: The first parameter,
409: .L xdrs ,
410: is an XDR stream handle.
411: The second parameter is the address of the number
412: that provides data to the stream or receives data from it.
413: All routines return TRUE if they complete successfully,
414: and FALSE otherwise.
415: .
416: .H 2 "Floating Point Filters"
417: .LP
418: The XDR library also provides primitive routines
419: for C's floating point types:
420: .LS
421: bool_t xdr_float(xdrs, fp)
422: XDR *xdrs;
423: float *fp;
424: .LE
425: .LS
426: bool_t xdr_double(xdrs, dp)
427: XDR *xdrs;
428: double *dp;
429: .LE
430: The first parameter,
431: .L xdrs
432: is an XDR stream handle.
433: The second parameter is the address
434: of the floating point number that provides data to the stream
435: or receives data from it.
436: All routines return TRUE if they complete successfully,
437: and FALSE otherwise.
438: .LP
439: Note: Since the numbers are represented in IEEE floating point,
440: routines may fail when decoding a valid IEEE representation
441: into a machine-specific representation, or vice-versa.
442: .
443: .H 2 "Enumeration Filters"
444: .LP
445: The XDR library provides a primitive for generic enumerations.
446: The primitive assumes that a C
447: .L enum
448: has the same representation inside the machine as a C integer.
449: The boolean type is an important instance of the
450: .L enum .
451: The external representation of a boolean
452: is always one (TRUE) or zero (FALSE).
453: .LS
454: #define bool_t int
455: #define FALSE 0
456: #define TRUE 1
457: .sp.5
458: #define enum_t int
459: .sp.5
460: bool_t xdr_enum(xdrs, ep)
461: XDR *xdrs;
462: enum_t *ep;
463: .sp.5
464: bool_t xdr_bool(xdrs, bp)
465: XDR *xdrs;
466: bool_t *bp;
467: .LE
468: The second parameters
469: .L ep
470: and
471: .L bp
472: are addresses of the associated type
473: that provides data to, or receives data from, the stream
474: .L xdrs .
475: The routines return TRUE if they complete successfully,
476: and FALSE otherwise.
477: .
478: .H 2 "No Data"
479: .LP
480: Occasionally, an XDR routine must be supplied to the RPC system,
481: even when no data is passed or required.
482: The library provides such a routine:
483: .LS
484: bool_t xdr_void(); /* always returns TRUE */
485: .LE
486: .
487: .H 2 "Constructed Data Type Filters"
488: .LP
489: Constructed or compound data type primitives
490: require more parameters and perform more complicated functions
491: then the primitives discussed above.
492: This section includes primitives for
493: strings, arrays, unions, and pointers to structures.
494: .LH
495: Constructed data type primitives may use memory management.
496: In many cases, memory is allocated when deserializing
497: data with XDR_DECODE.
498: Therefore, the XDR package must provide means to deallocate memory.
499: This is done by an XDR operation, XDR_FREE.
500: To review, the three XDR directional operations are
501: XDR_ENCODE, XDR_DECODE, and XDR_FREE.
502: .
503: .H 3 "Strings"
504: .LP
505: In C, a string is defined as a sequence of bytes
506: terminated by a null byte,
507: which is not considered when calculating string length.
508: However, when a string is passed or manipulated,
509: a pointer to it is employed.
510: Therefore, the XDR library defines a string to be a
511: .L "char *" ,
512: and not a sequence of characters.
513: The external representation of a string is drastically different
514: from its internal representation.
515: Externally, strings are represented as
516: sequences of ASCII characters,
517: while internally, they are represented with character pointers.
518: Conversion between the two representations
519: is accomplished with the routine
520: .L xdr_string() :
521: .LS
522: bool_t xdr_string(xdrs, sp, maxlength)
523: XDR *xdrs;
524: char **sp;
525: u_int maxlength;
526: .LE
527: The first parameter
528: .L xdrs
529: is the XDR stream handle.
530: The second parameter
531: .L sp
532: is a pointer to a string (type
533: .L "char **" ).
534: The third parameter
535: .L maxlength
536: specifies the maximum number of bytes allowed during encoding or decoding;
537: its value is usually specified by a protocol.
538: For example, a protocol specification may say
539: that a file name may be no longer than 255 characters.
540: The routine returns FALSE if the number of characters exceeds
541: .L maxlength ,
542: and TRUE if it doesn't.
543: .LP
544: The behavior of
545: .L xdr_string()
546: is similar to the behavior of other routines
547: discussed in this section.
548: The direction XDR_ENCODE is easiest to understand.
549: The parameter
550: .L sp
551: points to a string of a certain length;
552: if it does not exceed
553: .L maxlength ,
554: the bytes are serialized.
555: .LP
556: The effect of deserializing a string is subtle.
557: First the length of the incoming string is determined;
558: it must not exceed
559: .L maxlength .
560: Next
561: .L sp
562: is dereferenced; if the the value is NULL,
563: then a string of the appropriate length is allocated and
564: .L *sp
565: is set to this string.
566: If the original value of
567: .L *sp
568: is non-NULL, then the XDR package assumes
569: that a target area has been allocated,
570: which can hold strings no longer than
571: .L maxlength .
572: In either case, the string is decoded into the target area.
573: The routine then appends a null character to the string.
574: .LP
575: In the XDR_FREE operation,
576: the string is obtained by dereferencing
577: .L sp .
578: If the string is not NULL, it is freed and
579: .L *sp
580: is set to NULL.
581: In this operation,
582: .L xdr_string
583: ignores the
584: .L maxlength
585: parameter.
586: .
587: .H 3 "Byte Arrays"
588: .LP
589: Often variable-length arrays of bytes are preferable to strings.
590: Byte arrays differ from strings in the following three ways:
591: 1) the length of the array (the byte count) is explicitly
592: located in an unsigned integer,
593: 2) the byte sequence is not terminated by a null character, and
594: 3) the external representation of the bytes is the same as their
595: internal representation.
596: The primitive
597: .L xdr_bytes()
598: converts between the internal and external
599: representations of byte arrays:
600: .LS
601: bool_t xdr_bytes(xdrs, bpp, lp, maxlength)
602: XDR *xdrs;
603: char **bpp;
604: u_int *lp;
605: u_int maxlength;
606: .LE
607: The usage of the first, second and fourth parameters
608: are identical to the first, second and third parameters of
609: .L xdr_string() ,
610: respectively.
611: The length of the byte area is obtained by dereferencing
612: .L lp
613: when serializing;
614: .L *lp
615: is set to the byte length when deserializing.
616: .
617: .H 3 "Arrays"
618: .LP
619: The XDR library package provides a primitive
620: for handling arrays of arbitrary elements.
621: The
622: .L xdr_bytes()
623: routine treats a subset of generic arrays,
624: in which the size of array elements is known to be 1,
625: and the external description of each element is built-in.
626: The generic array primitive,
627: .L xdr_array()
628: requires parameters identical to those of
629: .L xdr_bytes()
630: plus two more:
631: the size of array elements,
632: and an XDR routine to handle each of the elements.
633: This routine is called to encode or decode
634: each element of the array.
635: .LS
636: bool_t xdr_array(xdrs, ap, lp, maxlength, elementsize, xdr_element)
637: XDR *xdrs;
638: char **ap;
639: u_int *lp;
640: u_int maxlength;
641: u_int elementsize;
642: bool_t (*xdr_element)();
643: .LE
644: The parameter
645: .L ap
646: is the address of the pointer to the array.
647: If
648: .L *ap
649: is NULL when the array is being deserialized,
650: XDR allocates an array of the appropriate size and sets
651: .L *ap
652: to that array.
653: The element count of the array is obtained from
654: .L *lp
655: when the array is serialized;
656: .L *lp
657: is set to the array length when the array is deserialized.
658: The parameter
659: .L maxlength
660: is the maximum number of elements that the array is allowed to have;
661: .L elementsize
662: is the byte size of each element of the array
663: (the C function
664: .L sizeof()
665: can be used to obtain this value).
666: The routine
667: .L xdr_element
668: is called to serialize, deserialize, or free
669: each element of the array.
670: .LP
671: .I Examples
672: .LP
673: Before defining more constructed data types,
674: it is appropriate to present three examples.
675: .LP
676: .I "Example A"
677: .LP
678: A user on a networked machine can be identified by
679: (a) the machine name, such as
680: .L krypton :
681: see
682: .I gethostname (3);
683: (b) the user's UID: see
684: .I geteuid (2);
685: and (c) the group numbers to which the user belongs: see
686: .I getgroups (2).
687: A structure with this information and its associated XDR routine
688: could be coded like this:
689: .LS
690: struct netuser {
691: char *nu_machinename;
692: int nu_uid;
693: u_int nu_glen;
694: int *nu_gids;
695: };
696: #define NLEN 255 /* machine names must be shorter than 256 chars */
697: #define NGRPS 20 /* user can't be a member of more than 20 groups */
698: .sp.5
699: bool_t
700: xdr_netuser(xdrs, nup)
701: XDR *xdrs;
702: struct netuser *nup;
703: {
704: return (xdr_string(xdrs, &nup->nu_machinename, NLEN) &&
705: xdr_int(xdrs, &nup->nu_uid) &&
706: xdr_array(xdrs, &nup->nu_gids, &nup->nu_glen, NGRPS,
707: sizeof (int), xdr_int));
708: }
709: .LE
710: .LP
711: .I "Example B"
712: .LP
713: A party of network users could be implemented
714: as an array of
715: .L netuser
716: structure.
717: The declaration and its associated XDR routines
718: are as follows:
719: .LS
720: struct party {
721: u_int p_len;
722: struct netuser *p_nusers;
723: };
724: #define PLEN 500 /* max number of users in a party */
725: .sp.5
726: bool_t
727: xdr_party(xdrs, pp)
728: XDR *xdrs;
729: struct party *pp;
730: {
731: return (xdr_array(xdrs, &pp->p_nusers, &pp->p_len, PLEN,
732: sizeof (struct netuser), xdr_netuser));
733: }
734: .LE
735: .LP
736: .I "Example C"
737: .LP
738: The well-known parameters to
739: .L main() ,
740: .L argc
741: and
742: .L argv
743: can be combined into a structure.
744: An array of these structures can make up a history of commands.
745: The declarations and XDR routines might look like:
746: .LS
747: struct cmd {
748: u_int c_argc;
749: char **c_argv;
750: };
751: #define ALEN 1000 /* args can be no longer than 1000 chars */
752: #define NARGC 100 /* commands may have no more than 100 args */
753: .sp.5
754: struct history {
755: u_int h_len;
756: struct cmd *h_cmds;
757: };
758: #define NCMDS 75 /* history is no more than 75 commands */
759: .LE
760: .LS
761: bool_t
762: xdr_wrap_string(xdrs, sp)
763: XDR *xdrs;
764: char **sp;
765: {
766: return (xdr_string(xdrs, sp, ALEN));
767: }
768: .LE
769: .LS
770: bool_t
771: xdr_cmd(xdrs, cp)
772: XDR *xdrs;
773: struct cmd *cp;
774: {
775: return (xdr_array(xdrs, &cp->c_argv, &cp->c_argc, NARGC,
776: sizeof (char *), xdr_wrap_string));
777: }
778: .LE
779: .LS
780: bool_t
781: xdr_history(xdrs, hp)
782: XDR *xdrs;
783: struct history *hp;
784: {
785: return (xdr_array(xdrs, &hp->h_cmds, &hp->h_len, NCMDS,
786: sizeof (struct cmd), xdr_cmd));
787: }
788: .LE
789: The most confusing part of this example is that the routine
790: .L xdr_wrap_string()
791: is needed to package the
792: .L xdr_string()
793: routine, because the implementation of
794: .L xdr_array()
795: only passes two parameters to the array element description routine;
796: .L xdr_wrap_string()
797: supplies the third parameter to
798: .L xdr_string() .
799: .LP
800: By now the recursive nature of the XDR library should be obvious.
801: Let's continue with more constructed data types.
802: .
803: .H 3 "Opaque Data"
804: .LP
805: In some protocols, handles are passed from a server to client.
806: The client passes the handle back to the server at some later time.
807: Handles are never inspected by clients;
808: they are obtained and submitted.
809: That is to say, handles are opaque.
810: The primitive
811: .L xdr_opaque()
812: is used for describing fixed sized, opaque bytes.
813: .LS
814: bool_t xdr_opaque(xdrs, p, len)
815: XDR *xdrs;
816: char *p;
817: u_int len;
818: .LE
819: The parameter
820: .L p
821: is the location of the bytes;
822: .L len
823: is the number of bytes in the opaque object.
824: By definition, the actual data
825: contained in the opaque object are not machine portable.
826: .
827: .H 3 "Fixed Sized Arrays"
828: .LP
829: The XDR library does not provide a primitive for fixed-length arrays
830: (the primitive
831: .L xdr_array()
832: is for varying-length arrays).
833: Example A could be rewritten to use fixed-sized arrays
834: in the following fashion:
835: .LS
836: #define NLEN 255 /* machine names must be shorter than 256 chars */
837: #define NGRPS 20 /* user cannot be a member of more than 20 groups */
838: .sp.5
839: struct netuser {
840: char *nu_machinename;
841: int nu_uid;
842: int nu_gids[NGRPS];
843: };
844: .LE
845: .LS
846: bool_t
847: xdr_netuser(xdrs, nup)
848: XDR *xdrs;
849: struct netuser *nup;
850: {
851: int i;
852: .sp.5
853: if (! xdr_string(xdrs, &nup->nu_machinename, NLEN))
854: return (FALSE);
855: if (! xdr_int(xdrs, &nup->nu_uid))
856: return (FALSE);
857: for (i = 0; i < NGRPS; i++) {
858: if (! xdr_int(xdrs, &nup->nu_gids[i]))
859: return (FALSE);
860: }
861: return (TRUE);
862: }
863: .LE
864: .LP
865: Exercise:
866: Rewrite example A so that it uses varying-length arrays and so that the
867: .L netuser
868: structure contains the actual
869: .L nu_gids
870: array body as in the example above.
871: .
872: .H 3 "Discriminated Unions"
873: .LP
874: The XDR library supports discriminated unions.
875: A discriminated union is a C union and an
876: .L enum_t
877: value that selects an ``arm'' of the union.
878: .LS
879: struct xdr_discrim {
880: enum_t value;
881: bool_t (*proc)();
882: };
883: .LE
884: .LS
885: bool_t xdr_union(xdrs, dscmp, unp, arms, defaultarm)
886: XDR *xdrs;
887: enum_t *dscmp;
888: char *unp;
889: struct xdr_discrim *arms;
890: bool_t (*defaultarm)(); /* may equal NULL */
891: .LE
892: First the routine translates the discriminant of the union located at
893: .L *dscmp .
894: The discriminant is always an
895: .L enum_t .
896: Next the union located at
897: .L *unp
898: is translated.
899: The parameter
900: .L arms
901: is a pointer to an array of
902: .L xdr_discrim
903: structures.
904: Each structure contains an order pair of
905: .L [value,proc] .
906: If the union's discriminant is equal to the associated
907: .L value ,
908: then the
909: .L proc
910: is called to translate the union.
911: The end of the
912: .L xdr_discrim
913: structure array is denoted by a routine of value NULL (0).
914: If the discriminant is not found in the
915: .L arms
916: array, then the
917: .L defaultarm
918: procedure is called if it is non-NULL;
919: otherwise the routine returns FALSE.
920: .LP
921: .I "Example D"
922: .LP
923: Suppose the type of a union may be integer,
924: character pointer (a string), or a
925: .L gnumbers
926: structure.
927: Also, assume the union and its current type
928: are declared in a structure.
929: The declaration is:
930: .LS
931: enum utype { INTEGER=1, STRING=2, GNUMBERS=3 };
932: .sp.5
933: struct u_tag {
934: enum utype utype; /* this is the union's discriminant */
935: union {
936: int ival;
937: char *pval;
938: struct gnumbers gn;
939: } uval;
940: };
941: .LE
942: The following constructs and XDR procedure (de)serialize
943: the discriminated union:
944: .LS
945: struct xdr_discrim u_tag_arms[4] = {
946: { INTEGER, xdr_int },
947: { GNUMBERS, xdr_gnumbers }
948: { STRING, xdr_wrap_string },
949: { __dontcare__, NULL }
950: /* always terminate arms with a NULL xdr_proc */
951: }
952: .LE
953: .LS
954: bool_t
955: xdr_u_tag(xdrs, utp)
956: XDR *xdrs;
957: struct u_tag *utp;
958: {
959: return (xdr_union(xdrs, &utp->utype, &utp->uval, u_tag_arms,
960: NULL));
961: }
962: .LE
963: The routine
964: .L xdr_gnumbers()
965: was presented in Section 2;
966: .L xdr_wrap_string()
967: was presented in example C.
968: The default arm parameter to
969: .L xdr_union()
970: (the last parameter) is NULL in this example.
971: Therefore the value of the union's discriminant legally
972: may take on only values listed in the
973: .L u_tag_arms
974: array.
975: This example also demonstrates that the elements of the arm's array
976: do not need to be sorted.
977: .LP
978: It is worth pointing out that the values of the discriminant
979: may be sparse, though in this example they are not.
980: It is always good
981: practice to assign explicitly integer values to each element of the
982: discriminant's type.
983: This practice both documents the external
984: representation of the discriminant and guarantees that different
985: C compilers emit identical discriminant values.
986: .LP
987: Exercise: Implement
988: .L xdr_union()
989: using the other primitives in this section.
990: .
991: .H 3 "Pointers"
992: .LP
993: In C it is often convenient to put pointers
994: to another structure within a structure.
995: The primitive
996: .L xdr_reference()
997: makes it easy to serialize, deserialize, and free
998: these referenced structures.
999: .LS
1000: bool_t xdr_reference(xdrs, pp, size, proc)
1001: XDR *xdrs;
1002: char **pp;
1003: u_int ssize;
1004: bool_t (*proc)();
1005: .LE
1006: .LP
1007: Parameter
1008: .L pp
1009: is the address of
1010: the pointer to the structure;
1011: parameter
1012: .L ssize
1013: is the size in bytes of the structure
1014: (use the C function
1015: .L sizeof()
1016: to obtain this value); and
1017: .L proc
1018: is the XDR routine that describes the structure.
1019: When decoding data, storage is allocated if
1020: .L *pp
1021: is NULL.
1022: .LP
1023: There is no need for a primitive
1024: .L xdr_struct()
1025: to describe structures within structures,
1026: because pointers are always sufficient.
1027: .LP
1028: Exercise: Implement
1029: .L xdr_reference()
1030: using
1031: .L xdr_array() .
1032: Warning:
1033: .L xdr_reference()
1034: and
1035: .L xdr_array()
1036: are NOT interchangeable external representations of data.
1037: .LP
1038: .I "Example E"
1039: .LP
1040: Suppose there is a structure containing a person's name
1041: and a pointer to a
1042: .L gnumbers
1043: structure containing the person's gross assets and liabilities.
1044: The construct is:
1045: .LS
1046: struct pgn {
1047: char *name;
1048: struct gnumbers *gnp;
1049: };
1050: .LE
1051: The corresponding XDR routine for this structure is:
1052: .LS
1053: bool_t
1054: xdr_pgn(xdrs, pp)
1055: XDR *xdrs;
1056: struct pgn *pp;
1057: {
1058: if (xdr_string(xdrs, &pp->name, NLEN) &&
1059: xdr_reference(xdrs, &pp->gnp, sizeof(struct gnumbers),
1060: xdr_gnumbers))
1061: return(TRUE);
1062: return(FALSE);
1063: }
1064: .LE
1065: .H 4 "Pointer Semantics and XDR"
1066: .LP
1067: In many applications,
1068: C programmers attach double meaning to the values of a pointer.
1069: Typically the value NULL (or zero) means data is not needed,
1070: yet some application-specific interpretation applies.
1071: In essence, the C programmer is encoding
1072: a discriminated union efficiently
1073: by overloading the interpretation of the value of a pointer.
1074: For instance, in example E a NULL pointer value for
1075: .L gnp
1076: could indicate that
1077: the person's assets and liabilities are unknown.
1078: That is, the pointer value encodes two things:
1079: whether or not the data is known;
1080: and if it is known, where it is located in memory.
1081: Linked lists are an extreme example of the use
1082: of application-specific pointer interpretation.
1083: .LP
1084: The primitive
1085: .L xdr_reference()
1086: cannot and does not attach any special
1087: meaning to a NULL-value pointer during serialization.
1088: That is, passing an address of a pointer whose value is NULL to
1089: .L xdr_reference()
1090: when serialing data will most likely cause a memory fault and, on
1091: .UX ,
1092: a core dump for debugging.
1093: .LP
1094: It is the explicit responsibility of the programmer
1095: to expand non-dereferenceable pointers into their specific semantics.
1096: This usually involves describing data with a two-armed discriminated union.
1097: One arm is used when the pointer is valid;
1098: the other is used when the pointer is invalid (NULL).
1099: Section 7 has an example (linked lists encoding) that deals
1100: with invalid pointer interpretation.
1101: .LP
1102: Exercise:
1103: After reading Section 7, return here and extend example E so that
1104: it can correctly deal with null pointer values.
1105: .LP
1106: Exercise:
1107: Using the
1108: .L xdr_union() ,
1109: .L xdr_reference()
1110: and
1111: .L xdr_void()
1112: primitives, implement a generic pointer handling primitive
1113: that implicitly deals with NULL pointers.
1114: The XDR library does not provide such a primitive
1115: because it does not want to give the illusion
1116: that pointers have meaning in the external world.
1117: .
1118: .H 2 "Non-filter Primitives"
1119: .LP
1120: XDR streams can be manipulated with
1121: the primitives discussed in this section.
1122: .LS
1123: u_int xdr_getpos(xdrs)
1124: XDR *xdrs;
1125: .LE
1126: .LS
1127: bool_t xdr_setpos(xdrs, pos)
1128: XDR *xdrs;
1129: u_int pos;
1130: .LE
1131: .LS
1132: xdr_destroy(xdrs)
1133: XDR *xdrs;
1134: .LE
1135: The routine
1136: .L xdr_getpos()
1137: returns an unsigned integer
1138: that describes the current position in the data stream.
1139: Warning: In some XDR streams, the returned value of
1140: .L xdr_getpos()
1141: is meaningless;
1142: the routine returns a \-1 in this case
1143: (though \-1 should be a legitimate value).
1144: .LP
1145: The routine
1146: .L xdr_setpos()
1147: sets a stream position to
1148: .L pos .
1149: Warning: In some XDR streams, setting a position is impossible;
1150: in such cases,
1151: .L xdr_setpos()
1152: will return FALSE.
1153: This routine will also fail if the requested position is out-of-bounds.
1154: The definition of bounds varies from stream to stream.
1155: .LP
1156: The
1157: .L xdr_destroy()
1158: primitive destroys the XDR stream.
1159: Usage of the stream
1160: after calling this routine is undefined.
1161: .
1162: .H 2 "XDR Operation Directions"
1163: .LP
1164: At times you may wish to optimize XDR routines by taking
1165: advantage of the direction of the operation (XDR_ENCODE,
1166: XDR_DECODE, or XDR_FREE).
1167: The value
1168: .L xdrs->x_op
1169: always contains the
1170: direction of the XDR operation.
1171: Programmers are not encouraged to take advantage of this information.
1172: Therefore, no example is presented here.
1173: However, an example in Section 7
1174: demonstrates the usefulness of the
1175: .L xdrs->x_op
1176: field.
1177: .bp
1178: .
1179: .H 1 "XDR Stream Access"
1180: .LP
1181: An XDR stream is obtained by calling the appropriate creation routine.
1182: These creation routines take arguments that are tailored to the
1183: specific properties of the stream.
1184: .LP
1185: Streams currently exist for (de)serialization of data to or from
1186: standard I/O FILE streams,
1187: TCP/IP connections and
1188: .UX
1189: files, and memory.
1190: Section 5 documents the XDR object and how to make
1191: new XDR streams when they are required.
1192: .
1193: .H 2 "Standard I/O Streams"
1194: .LP
1195: XDR streams can be interfaced to standard I/O using the
1196: .L xdrstdio_create()
1197: routine as follows:
1198: .LS
1199: #include <stdio.h>
1200: #include <rpc/rpc.h> /* xdr streams are a part of the rpc library */
1201: .LE
1202: .LS
1203: void
1204: xdrstdio_create(xdrs, fp, x_op)
1205: XDR *xdrs;
1206: FILE *fp;
1207: enum xdr_op x_op;
1208: .LE
1209: The routine
1210: .L xdrstdio_create()
1211: initializes an XDR stream pointed to by
1212: .L xdrs .
1213: The XDR stream interfaces to the standard I/O library.
1214: Parameter
1215: .L fp
1216: is an open file, and
1217: .L x_op
1218: is an XDR direction.
1219: .
1220: .H 2 "Memory Streams"
1221: .LP
1222: Memory streams allow the streaming of data into or out of
1223: a specified area of memory:
1224: .LS
1225: #include <rpc/rpc.h>
1226: .sp.5
1227: void
1228: xdrmem_create(xdrs, addr, len, x_op)
1229: XDR *xdrs;
1230: char *addr;
1231: u_int len;
1232: enum xdr_op x_op;
1233: .LE
1234: The routine
1235: .L xdrmem_create()
1236: initializes an XDR stream in local memory.
1237: The memory is pointed to by parameter
1238: .L addr ;
1239: parameter
1240: .L len
1241: is the length in bytes of the memory.
1242: The parameters
1243: .L xdrs
1244: and
1245: .L x_op
1246: are identical to the corresponding parameters of
1247: .L xdrstdio_create() .
1248: Currently, the UDP/IP implementation of RPC uses
1249: .L xdrmem_create() .
1250: Complete call or result messages are built in memory before calling the
1251: .L sendto()
1252: system routine.
1253: .
1254: .H 2 "Record (TCP/IP) Streams"
1255: .LP
1256: A record stream is an XDR stream built on top of
1257: a record marking standard that is built on top of the
1258: .UX
1259: file or 4.2 BSD connection interface.
1260: .LS
1261: #include <rpc/rpc.h> /* xdr streams are a part of the rpc library */
1262: .sp.5
1263: xdrrec_create(xdrs, sendsize, recvsize, iohandle, readproc, writeproc)
1264: XDR *xdrs;
1265: u_int sendsize, recvsize;
1266: char *iohandle;
1267: int (*readproc)(), (*writeproc)();
1268: .LE
1269: The routine
1270: .L xdrrec_create()
1271: provides an XDR stream interface that allows for a bidirectional,
1272: arbitrarily long sequence of records.
1273: The contents of the records are meant to be data in XDR form.
1274: The stream's primary use is for interfacing RPC to TCP connections.
1275: However, it can be used to stream data into or out of normal
1276: .UX
1277: files.
1278: .LP
1279: The parameter
1280: .L xdrs
1281: is similar to the corresponding parameter described above.
1282: The stream does its own data buffering similar to that of standard I/O.
1283: The parameters
1284: .L sendsize
1285: and
1286: .L recvsize
1287: determine the size in bytes of the output and input buffers, respectively;
1288: if their values are zero (0), then predetermined defaults are used.
1289: When a buffer needs to be filled or flushed, the routine
1290: .L readproc
1291: or
1292: .L writeproc
1293: is called, respectively.
1294: The usage and behavior of these
1295: routines are similar to the
1296: .UX
1297: system calls
1298: .L read()
1299: and
1300: .L write() .
1301: However,
1302: the first parameter to each of these routines is the opaque parameter
1303: .L iohandle .
1304: The other two parameters
1305: .L buf "" (
1306: and
1307: .L nbytes )
1308: and the results
1309: (byte count) are identical to the system routines.
1310: If
1311: .L xxx
1312: is
1313: .L readproc
1314: or
1315: .L writeproc ,
1316: then it has the following form:
1317: .LS
1318: /* returns the actual number of bytes transferred.
1319: * -1 is an error
1320: */
1321: int
1322: xxx(iohandle, buf, len)
1323: char *iohandle;
1324: char *buf;
1325: int nbytes;
1326: .LE
1327: The XDR stream provides means for delimiting records in the byte stream.
1328: The implementation details of delimiting records in a stream
1329: are discussed in appendix 1.
1330: The primitives that are specific to record streams are as follows:
1331: .LS
1332: bool_t
1333: xdrrec_endofrecord(xdrs, flushnow)
1334: XDR *xdrs;
1335: bool_t flushnow;
1336: .sp.5
1337: bool_t
1338: xdrrec_skiprecord(xdrs)
1339: XDR *xdrs;
1340: .sp.5
1341: bool_t
1342: xdrrec_eof(xdrs)
1343: XDR *xdrs;
1344: .LE
1345: The routine
1346: .L xdrrec_endofrecord()
1347: causes the current outgoing data to be marked as a record.
1348: If the parameter
1349: .L flushnow
1350: is TRUE, then the stream's
1351: .L writeproc()
1352: will be called; otherwise,
1353: .L writeproc()
1354: will be called when the output buffer has been filled.
1355: .LP
1356: The routine
1357: .L xdrrec_skiprecord()
1358: causes an input stream's position to be moved past
1359: the current record boundary and onto the
1360: beginning of the next record in the stream.
1361: .LP
1362: If there is no more data in the stream's input buffer,
1363: then the routine
1364: .L xdrrec_eof()
1365: returns TRUE.
1366: That is not to say that there is no more data
1367: in the underlying file descriptor.
1368: .
1369: .H 1 "XDR Stream Implementation"
1370: .LP
1371: This section provides the abstract data types needed
1372: to implement new instances of XDR streams.
1373: .
1374: .H 2 "The XDR Object"
1375: .LP
1376: The following structure defines the interface to an XDR stream:
1377: .LS 0
1378: enum xdr_op { XDR_ENCODE = 0, XDR_DECODE = 1, XDR_FREE = 2 };
1379: .sp.5
1380: typedef struct {
1381: enum xdr_op x_op; /* operation; fast additional param */
1382: struct xdr_ops {
1383: bool_t (*x_getlong)(); /* get a long from underlying stream */
1384: bool_t (*x_putlong)(); /* put a long to " */
1385: bool_t (*x_getbytes)(); /* get some bytes from " */
1386: bool_t (*x_putbytes)(); /* put some bytes to " */
1387: u_int (*x_getpostn)(); /* returns byte offset from beginning */
1388: bool_t (*x_setpostn)(); /* repositions position in stream */
1389: caddr_t (*x_inline)(); /* buf quick ptr to buffered data */
1390: VOID (*x_destroy)(); /* free privates of this xdr_stream */
1391: } *x_ops;
1392: caddr_t x_public; /* users' data */
1393: caddr_t x_private; /* pointer to private data */
1394: caddr_t x_base; /* private used for position info */
1395: int x_handy; /* extra private word */
1396: } XDR;
1397: .LE
1398: The
1399: .L x_op
1400: field is the current operation being performed on the stream.
1401: This field is important to the XDR primitives,
1402: but should not affect a stream's implementation.
1403: That is, a stream's implementation should not depend
1404: on this value.
1405: The fields
1406: .L x_private ,
1407: .L x_base ,
1408: and
1409: .L x_handy
1410: are private to the particular
1411: stream's implementation.
1412: The field
1413: .L x_public
1414: is for the XDR client and should never be used by
1415: the XDR stream implementations or the XDR primitives.
1416: .LP
1417: Macros for accessing operations
1418: .L x_getpostn() ,
1419: .L x_setpostn() ,
1420: and
1421: .L x_destroy()
1422: were defined in Section 3.6.
1423: The operation
1424: .L x_inline()
1425: takes two parameters:
1426: an XDR *, and an unsigned integer, which is a byte count.
1427: The routine returns a pointer to a piece of
1428: the stream's internal buffer.
1429: The caller can then use the buffer segment for any purpose.
1430: From the stream's point of view, the bytes in the
1431: buffer segment have been consumed or put.
1432: The routine may return NULL
1433: if it cannot return a buffer segment of the requested size.
1434: (The
1435: .L x_inline
1436: routine is for cycle squeezers.
1437: Use of the resulting buffer is not data-portable.
1438: Users are encouraged not to use this feature.)
1439: .LP
1440: The operations
1441: .L x_getbytes()
1442: and
1443: .L x_putbytes()
1444: blindly get and put sequences of bytes
1445: from or to the underlying stream;
1446: they return TRUE if they are successful,
1447: and FALSE otherwise.
1448: The routines have identical parameters (replace
1449: .L xxx ):
1450: .LS
1451: bool_t
1452: xxxbytes(xdrs, buf, bytecount)
1453: XDR *xdrs;
1454: char *buf;
1455: u_int bytecount;
1456: .LE
1457: The operations
1458: .L x_getlong()
1459: and
1460: .L x_putlong()
1461: receive and put
1462: long numbers from and to the data stream.
1463: It is the responsibility of these routines
1464: to translate the numbers between the machine representation
1465: and the (standard) external representation.
1466: The
1467: .UX
1468: primitives
1469: .L htonl()
1470: and
1471: .L ntohl()
1472: can be helpful in accomplishing this.
1473: Section 6 defines the standard representation of numbers.
1474: The higher-level XDR implementation assumes that
1475: signed and unsigned long integers contain the same number of bits,
1476: and that nonnegative integers
1477: have the same bit representations as unsigned integers.
1478: The routines return TRUE if they succeed,
1479: and FALSE otherwise.
1480: They have identical parameters:
1481: .LS
1482: bool_t
1483: xxxlong(xdrs, lp)
1484: XDR *xdrs;
1485: long *lp;
1486: .LE
1487: Implementors of new XDR streams must make an XDR structure
1488: (with new operation routines) available to clients,
1489: using some kind of create routine.
1490: .bp
1491: .
1492: .H 1 "XDR Standard"
1493: .LP
1494: This section defines the external data representation standard.
1495: The standard is independent of languages,
1496: operating systems and hardware architectures.
1497: Once data is shared among machines, it should not matter that the data
1498: was produced on a Sun, but is consumed by a VAX (or vice versa).
1499: Similarly the choice of operating systems should have no influence
1500: on how the data is represented externally.
1501: For programming languages,
1502: data produced by a C program should be readable
1503: by a FORTRAN or Pascal program.
1504: .LP
1505: The external data representation standard depends on the assumption that
1506: bytes (or octets) are portable.
1507: A byte is defined to be eight bits of data.
1508: It is assumed that hardware
1509: that encodes bytes onto various media
1510: will preserve the bytes' meanings
1511: across hardware boundaries.
1512: For example, the Ethernet standard suggests that bytes be
1513: encoded ``little endian'' style.
1514: Both Sun and VAX hardware implementations
1515: adhere to the standard.
1516: .LP
1517: The XDR standard also suggests a language used to describe data.
1518: The language is a bastardized C;
1519: it is a data description language, not a programming language.
1520: (The Xerox Courier Standard uses bastardized Mesa
1521: as its data description language.)
1522: .
1523: .H 2 "Basic Block Size"
1524: .LP
1525: The representation of all items requires
1526: a multiple of four bytes (or 32 bits) of data.
1527: The bytes are numbered
1528: $0$ through $n-1$, where $(n ~ \fRmod\fP ~ 4) = 0$.
1529: The bytes are read or written to some byte stream
1530: such that byte $m$ always precedes byte $m+1$.
1531: .
1532: .H 2 "Integer"
1533: .LP
1534: An XDR signed integer is a 32-bit datum
1535: that encodes an integer in the range
1536: .L [-2147483648,2147483647] .
1537: The integer is represented in two's complement notation.
1538: The most and least significant bytes are 0 and 3, respectively.
1539: The data description of integers is
1540: .L integer .
1541: .
1542: .H 2 "Unsigned Integer"
1543: .LP
1544: An XDR unsigned integer is a 32-bit datum
1545: that encodes a nonnegative integer in the range
1546: .L [0,4294967295] .
1547: It is represented by an unsigned binary number whose most
1548: and least significant bytes are 0 and 3, respectively.
1549: The data description of unsigned integers is
1550: .L unsigned .
1551: .
1552: .H 2 "Enumerations"
1553: .LP
1554: Enumerations have the same representation as integers.
1555: Enumerations are handy for describing subsets of the integers.
1556: The data description of enumerated data is as follows:
1557: .LS
1558: typedef enum { name = value, .... } type-name;
1559: .LE
1560: For example the three colors red, yellow and blue
1561: could be described by an enumerated type:
1562: .LS
1563: typedef enum { RED = 2, YELLOW = 3, BLUE = 5 } colors;
1564: .LE
1565: .
1566: .H 2 "Booleans"
1567: .LP
1568: Booleans are important enough and occur frequently enough
1569: to warrant their own explicit type in the standard.
1570: Boolean is an enumeration with the
1571: following form:
1572: .LS
1573: typedef enum { FALSE = 0, TRUE = 1 } boolean;
1574: .LE
1575: .
1576: .H 2 "Hyper Integer and Hyper Unsigned"
1577: .LP
1578: The standard also defines 64-bit (8-byte) numbers called
1579: .L "hyper integer"
1580: and
1581: .L "hyper unsigned" .
1582: Their representations are the obvious extensions of
1583: the integer and unsigned defined above.
1584: The most and least significant bytes are 0 and 7, respectively.
1585: .
1586: .H 2 "Floating Point and Double Precision"
1587: .LP
1588: The standard defines the encoding for the floating point data types
1589: .L float
1590: (32 bits or 4 bytes) and
1591: .L double
1592: (64 bits or 8 bytes).
1593: The encoding used is the IEEE standard for normalized
1594: single- and double-precision floating point numbers.
1595: See the IEEE floating point standard for more information.
1596: The standard encodes the following three fields,
1597: which describe the floating point number:
1598: .IP \fIS\fP
1599: The sign of the number.
1600: Values 0 and 1 represent
1601: positive and negative, respectively.
1602: .IP \fIE\fP
1603: The exponent of the number, base 2.
1604: Floats devote 8 bits to this field,
1605: while doubles devote 11 bits.
1606: The exponents for float and double are
1607: biased by 127 and 1023, respectively.
1608: .IP \fIF\fP
1609: The fractional part of the number's mantissa, base 2.
1610: Floats devote 23 bits to this field,
1611: while doubles devote 52 bits.
1612: .LP
1613: Therefore, the floating point number is described by:
1614: .EQ
1615: (-1) sup S * 2 sup { E - Bias } * 1.F
1616: .EN
1617: .LP
1618: Just as the most and least significant bytes of a number are 0 and 3,
1619: the most and least significant bits of
1620: a single-precision floating point number are 0 and 31.
1621: The beginning bit (and most significant bit) offsets
1622: of $S$, $E$, and $F$ are 0, 1, and 9, respectively.
1623: .LP
1624: Doubles have the analogous extensions.
1625: The beginning bit (and
1626: most significant bit) offsets of $S$, $E$, and $F$
1627: are 0, 1, and 12, respectively.
1628: .LP
1629: The IEEE specification should be consulted concerning the encoding for
1630: signed zero, signed infinity (overflow), and denormalized numbers (underflow).
1631: Under IEEE specifications, the ``NaN'' (not a number)
1632: is system dependent and should not be used.
1633: .
1634: .H 2 "Opaque Data"
1635: .LP
1636: At times fixed-sized uninterpreted data
1637: needs to be passed among machines.
1638: This data is called
1639: .L opaque
1640: and is described as:
1641: .LS
1642: typedef opaque type-name[n];
1643: opaque name[n];
1644: .LE
1645: where
1646: .L n
1647: is the (static) number of bytes necessary to contain the opaque data.
1648: If
1649: .L n
1650: is not a multiple of four, then the
1651: .L n
1652: bytes are followed by enough (up to 3) zero-valued bytes
1653: to make the total byte count of the opaque object a multiple of four.
1654: .
1655: .H 2 "Counted Byte Strings"
1656: .LP
1657: The standard defines a string of $n$ (numbered $0$ through $n-1$)
1658: bytes to be the number $n$ encoded as
1659: .L unsigned ,
1660: and followed by the $n$ bytes of the string.
1661: If $n$ is not a multiple of four,
1662: then the $n$ bytes are followed by
1663: enough (up to 3) zero-valued bytes
1664: to make the total byte count a multiple of four.
1665: The data description of strings is as follows:
1666: .LS
1667: typedef string type-name<N>;
1668: typedef string type-name<>;
1669: string name<N>;
1670: string name<>;
1671: .LE
1672: Note that the data description language uses angle brackets (< and >)
1673: to denote anything that is varying-length
1674: (as opposed to square brackets to denote fixed-length sequences of data).
1675: .LP
1676: The constant
1677: .L N
1678: denotes an upper bound of the number of bytes that a
1679: string may contain.
1680: If
1681: .L N
1682: is not specified, it is assumed to be $2 sup 32 - 1$,
1683: the maximum length.
1684: The constant
1685: .L N
1686: would normally be found in a protocol specification.
1687: For example, a filing protocol may state
1688: that a file name can be no longer than 255 bytes, such as:
1689: .LS
1690: string filename<255>;
1691: .LE
1692: .LP
1693: The XDR specification does not say what the
1694: individual bytes of a string represent;
1695: this important information is left to higher-level specifications.
1696: A reasonable default is to assume
1697: that the bytes encode ASCII characters.
1698: .
1699: .H 2 "Fixed Arrays"
1700: .LP
1701: The data description for fixed-size arrays of
1702: homogeneous elements is as follows:
1703: .LS
1704: typedef elementtype type-name[n];
1705: elementtype name[n];
1706: .LE
1707: Fixed-size arrays of elements numbered $0$ through $n-1$
1708: are encoded by individually encoding the elements of the array
1709: in their natural order, $0$ through $n-1$.
1710: .
1711: .H 2 "Counted Arrays"
1712: .LP
1713: Counted arrays provide the ability to encode varyiable-length arrays
1714: of homogeneous elements.
1715: The array is encoded as:
1716: the element count $n$ (an unsigned integer),
1717: followed by the encoding of each of the array's elements,
1718: starting with element $0$ and progressing through element $n-1$.
1719: The data description for counted arrays
1720: is similar to that of counted strings:
1721: .LS
1722: typedef elementtype type-name<N>;
1723: typedef elementtype type-name<>;
1724: elementtype name<N>;
1725: elementtype name<>;
1726: .LE
1727: Again, the constant
1728: .L N
1729: specifies the maximum acceptable
1730: element count of an array; if
1731: .L N
1732: is not specified, it is assumed to be $2 sup 32 - 1$.
1733: .
1734: .H 2 "Structures"
1735: .LP
1736: The data description for structures is very similar to
1737: that of standard C:
1738: .LS
1739: typedef struct {
1740: component-type component-name;
1741: ...
1742: } type-name;
1743: .LE
1744: The components of the structure are encoded
1745: in the order of their declaration in the structure.
1746: .
1747: .H 2 "Discriminated Unions"
1748: .LP
1749: A discriminated union is a type composed of a discriminant followed by a type
1750: selected from a set of prearranged types according to the value of the
1751: discriminant.
1752: The type of the discriminant is always an enumeration.
1753: The component types are called ``arms'' of the union.
1754: The discriminated union is encoded as its discriminant followed by
1755: the encoding of the implied arm.
1756: The data description for discriminated unions is as follows:
1757: .LS
1758: typedef union switch (discriminant-type) {
1759: discriminant-value: arm-type;
1760: ...
1761: default: default-arm-type;
1762: } type-name;
1763: .LE
1764: The default arm is optional.
1765: If it is not specified, then a valid
1766: encoding of the union cannot take on unspecified discriminant values.
1767: Most specifications neither need nor use default arms.
1768: .
1769: .H 2 "Missing Specifications"
1770: .LP
1771: The standard lacks representations for bit fields and bitmaps,
1772: since the standard is based on bytes.
1773: This is not to say that no specification should be attempted.
1774: .
1775: .H 2 "Library Primitive / XDR Standard Cross Reference"
1776: .LP
1777: The following table describes the association between
1778: the C library primitives discussed in Section 3,
1779: and the standard data types defined in this section:
1780: .LP
1781: .TS
1782: center box;
1783: r | c | l.
1784: C Primitive XDR Type Sections
1785: =
1786: xdr_int
1787: xdr_long integer 3.1, 6.2
1788: xdr_short
1789: _
1790: xdr_u_int
1791: xdr_u_long unsigned 3.1, 6.3
1792: xdr_u_short
1793: _
1794: - hyper integer 6.6
1795: hyper unsigned
1796: _
1797: xdr_float float 3.2, 6.7
1798: _
1799: xdr_double double 3.2, 6.7
1800: _
1801: xdr_enum enum_t 3.3, 6.4
1802: _
1803: xdr_bool bool_t 3.3, 6.5
1804: _
1805: xdr_string string 3.5.1, 6.9
1806: xdr_bytes 3.5.2
1807: _
1808: xdr_array (varying arrays) 3.5.3, 6.11
1809: _
1810: - (fixed arrays) 3.5.5, 6.10
1811: _
1812: xdr_opaque opaque 3.5.4, 6.8
1813: _
1814: xdr_union union 3.5.6, 6.13
1815: _
1816: xdr_reference - 3.5.7
1817: _
1818: - struct 6.6
1819: .TE
1820: .bp
1821: .
1822: .H 1 "Advanced Topics"
1823: .LP
1824: This section describes techniques for passing data structures
1825: that are not covered in the preceding sections.
1826: Such structures include linked lists (of arbitrary lengths).
1827: Unlike the simpler examples covered in the earlier sections,
1828: the following examples are written using both
1829: the XDR C library routines and the XDR data description language.
1830: Section 6 describes the XDR data definition language used below.
1831: .
1832: .H 2 "Linked Lists"
1833: .LP
1834: The last example in Section 2 presented a C data structure and its
1835: associated XDR routines for a person's gross assets and liabilities.
1836: The example is duplicated below:
1837: .LS
1838: struct gnumbers {
1839: long g_assets;
1840: long g_liabilities;
1841: };
1842: .sp.5
1843: bool_t
1844: xdr_gnumbers(xdrs, gp)
1845: XDR *xdrs;
1846: struct gnumbers *gp;
1847: {
1848: if (xdr_long(xdrs, &(gp->g_assets)))
1849: return (xdr_long(xdrs, &(gp->g_liabilities)));
1850: return (FALSE);
1851: }
1852: .LE
1853: Now assume that we wish to implement a linked list of such information.
1854: A data structure could be constructed as follows:
1855: .LS
1856: typedef struct gnnode {
1857: struct gnumbers gn_numbers;
1858: struct gnnode *nxt;
1859: };
1860: .sp.5
1861: typedef struct gnnode *gnumbers_list;
1862: .LE
1863: The head of the linked list can be thought of as the data object;
1864: that is, the head is not merely a convenient shorthand for a structure.
1865: Similarly the
1866: .L nxt
1867: field is used to indicate whether or not the object has terminated.
1868: Unfortunately, if the object continues, the
1869: .L nxt
1870: field is also the address
1871: of where it continues.
1872: The link addresses carry no useful information when
1873: the object is serialized.
1874: .LP
1875: The XDR data description of this linked list is described by the
1876: recursive type declaration of gnumbers_list:
1877: .LS
1878: struct gnumbers {
1879: unsigned g_assets;
1880: unsigned g_liabilities;
1881: };
1882: .LE
1883: .LS
1884: typedef union switch (boolean) {
1885: case TRUE: struct {
1886: struct gnumbers current_element;
1887: gnumbers_list rest_of_list;
1888: };
1889: case FALSE: struct {};
1890: } gnumbers_list;
1891: .LE
1892: In this description,
1893: the boolean indicates whether there is more data following it.
1894: If the boolean is FALSE,
1895: then it is the last data field of the structure.
1896: If it is TRUE, then it is followed by a
1897: .L gnumbers
1898: structure and (recursively) by a
1899: .L gnumbers_list
1900: (the rest of the object).
1901: Note that the C declaration has no boolean explicitly declared in it
1902: (though the
1903: .L nxt
1904: field implicitly carries the information), while
1905: the XDR data description has no pointer explicitly declared in it.
1906: .LP
1907: Hints for writing a set of XDR routines to successfully (de)serialize
1908: a linked list of entries can be taken
1909: from the XDR description of the pointer-less data.
1910: The set consists of the mutually recursive routines
1911: .L xdr_gnumbers_list ,
1912: .L xdr_wrap_list ,
1913: and
1914: .L xdr_gnnode .
1915: .LS
1916: bool_t
1917: xdr_gnnode(xdrs, gp)
1918: XDR *xdrs;
1919: struct gnnode *gp;
1920: {
1921: return (xdr_gnumbers(xdrs, &(gp->gn_numbers)) &&
1922: xdr_gnumbers_list(xdrs, &(gp->nxt)) );
1923: }
1924: .LE
1925: .LS
1926: bool_t
1927: xdr_wrap_list(xdrs, glp)
1928: XDR *xdrs;
1929: gnumbers_list *glp;
1930: {
1931: return (xdr_reference(xdrs, glp, sizeof(struct gnnode),
1932: xdr_gnnode));
1933: }
1934: .LE
1935: .LS
1936: struct xdr_discrim choices[2] = {
1937: /* called if another node needs (de)serializing */
1938: { TRUE, xdr_wrap_list },
1939: /* called when there are no more nodes to be (de)serialized */
1940: { FALSE, xdr_void }
1941: }
1942: .sp.5
1943: bool_t
1944: xdr_gnumbers_list(xdrs, glp)
1945: XDR *xdrs;
1946: gnumbers_list *glp;
1947: {
1948: bool_t more_data;
1949: .sp.5
1950: more_data = (*glp != (gnumbers_list)NULL);
1951: return (xdr_union(xdrs, &more_data, glp, choices, NULL);
1952: }
1953: .LE
1954: The entry routine is
1955: .L xdr_gnumbers_list() ;
1956: its job is to translate between the boolean value
1957: .L more_data
1958: and the list pointer values.
1959: If there is no more data, the
1960: .L xdr_union()
1961: primitive calls
1962: .L xdr_void
1963: and the recursion is terminated.
1964: Otherwise,
1965: .L xdr_union()
1966: calls
1967: .L xdr_wrap_list() ,
1968: whose job is to dereference the list pointers.
1969: The
1970: .L xdr_gnnode()
1971: routine actually (de)serializes data of the current node
1972: of the linked list, and recursively calls
1973: .L xdr_gnumbers_list()
1974: to handle the remainder of the list.
1975: .LP
1976: You should convince yourself that these routines function correctly in
1977: all three directions (XDR_ENCODE, XDR_DECODE and XDR_FREE)
1978: for linked lists of any length (including zero).
1979: Note that the boolean
1980: .L more_data
1981: is always initialized, but in the XDR_DECODE case
1982: it is overwritten by an externally generated value.
1983: Also note that the value of the
1984: .L bool_t
1985: is lost in the stack.
1986: The essence of the value is reflected in the list's pointers.
1987: .LP
1988: The unfortunate side effect of (de)serializing a list
1989: with these routines is that the C stack grows linearly
1990: with respect to the number of nodes in the list.
1991: This is due to the recursion.
1992: The routines are also hard to
1993: code (and understand) due to the number and nature of primitives involved
1994: (such as
1995: .L xdr_reference ,
1996: .L xdr_union ,
1997: and
1998: .L xdr_void ).
1999: .LP
2000: The following routine collapses the recursive routines.
2001: It also has other optimizations that are discussed below.
2002: .LS
2003: bool_t
2004: xdr_gnumbers_list(xdrs, glp)
2005: XDR *xdrs;
2006: gnumbers_list *glp;
2007: {
2008: bool_t more_data;
2009: .sp.5
2010: while (TRUE) {
2011: more_data = (*glp != (gnumbers_list)NULL);
2012: if (! xdr_bool(xdrs, &more_data))
2013: return (FALSE);
2014: if (! more_data)
2015: return (TRUE); /* we are done */
2016: if (! xdr_reference(xdrs, glp, sizeof(struct gnnode),
2017: xdr_gnumbers))
2018: return (FALSE);
2019: glp = &((*glp)->nxt);
2020: }
2021: }
2022: .LE
2023: The claim is that this one routine is easier to code and understand than the
2024: three recursive routines above.
2025: (It is also buggy, as discussed below.)
2026: The parameter
2027: .L glp
2028: is treated as the address of the pointer
2029: to the head of the
2030: remainder of the list to be (de)serialized.
2031: Thus,
2032: .L glp
2033: is set to the
2034: address of the current node's
2035: .L nxt
2036: field at the end of the while loop.
2037: The discriminated union is implemented in-line; the variable
2038: .L more_data
2039: has the same use in this routine as in the routines above.
2040: Its value is
2041: recomputed and re-(de)serialized each iteration of the loop.
2042: Since
2043: .L *glp
2044: is a pointer to a node, the pointer is dereferenced using
2045: .L xdr_reference() .
2046: Note that the third parameter is truly the size of a node
2047: (data values plus
2048: .L nxt
2049: pointer), while
2050: .L xdr_gnumbers()
2051: only (de)serializes the data values.
2052: We can get away with this tricky optimization only because the
2053: .L nxt
2054: data comes after all legitimate external data.
2055: .LP
2056: The routine is buggy in the XDR_FREE case.
2057: The bug is that
2058: .L xdr_reference()
2059: will free the node
2060: .L *glp .
2061: Upon return the assignment
2062: .L "glp = &((*glp)->nxt)"
2063: cannot be guaranteed to work since
2064: .L *glp
2065: is no longer a legitimate node.
2066: The following is a rewrite that works in all cases.
2067: The hard part is to avoid dereferencing a pointer
2068: which has not been initialized or which has been freed.
2069: .LS
2070: bool_t
2071: xdr_gnumbers_list(xdrs, glp)
2072: XDR *xdrs;
2073: gnumbers_list *glp;
2074: {
2075: bool_t more_data;
2076: bool_t freeing;
2077: gnumbers_list *next; /* the next value of glp */
2078: .sp.5
2079: freeing = (xdrs->x_op == XDR_FREE);
2080: while (TRUE) {
2081: more_data = (*glp != (gnumbers_list)NULL);
2082: if (! xdr_bool(xdrs, &more_data))
2083: return (FALSE);
2084: if (! more_data)
2085: return (TRUE); /* we are done */
2086: if (freeing)
2087: next = &((*glp)->nxt);
2088: if (! xdr_reference(xdrs, glp, sizeof(struct gnnode),
2089: xdr_gnumbers))
2090: return (FALSE);
2091: glp = (freeing) ? next : &((*glp)->nxt);
2092: }
2093: }
2094: .LE
2095: Note that this is the first example in this document
2096: that actually inspects the direction of the operation
2097: .L xdrs->x_op ). (
2098: The claim is that the correct iterative implementation is still
2099: easier to understand or code than the recursive implementation.
2100: It is certainly more efficient with respect to C stack requirements.
2101: .
2102: .H A "The Record Marking Standard"
2103: .LP
2104: A record is composed of one or more record fragments.
2105: A record fragment is a four-byte header followed by
2106: $ 0 ~ "\fRto\fP" ~ {2 sup 31} - 1$ bytes of fragment data.
2107: The bytes encode an unsigned binary number;
2108: as with XDR integers, the byte order is from highest to lowest.
2109: The number encodes two values \(em
2110: a boolean that indicates whether the fragment is the last fragment
2111: of the record (bit value 1 implies the fragment is the last fragment),
2112: and a 31-bit unsigned binary value
2113: which is the length in bytes of the fragment's data.
2114: The boolean value is the high-order bit of the
2115: header; the length is the 31 low-order bits.
2116: .LP
2117: (Note that this record specification is
2118: .L not
2119: in XDR standard form
2120: and cannot be implemented using XDR primitives!)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.