InomHitta mer dokumentationSupportresurser som ingår | Ladda ner denna bok i PDF (699 KB)
Appendix C XDR Protocol SpecificationThis appendix contains the XDR Protocol Language Specification. XDR Protocol IntroductionExternal data representation (XDR) is a standard for the description and encoding of data. The XDR protocol is useful for transferring data between different computer architectures and has been used to communicate data between such diverse machines as the Sun® Workstation®, VAX®, IBM® PC, and Cray. XDR fits into the ISO reference model's presentation layer (layer 6) and is roughly analogous in purpose to X.409, ISO Abstract Syntax Notation. The major difference between the two is that XDR uses implicit typing, while X.409 uses explicit typing. XDR uses a language to describe data formats and only can be used to describe data; it is not a programming language. This language makes it possible to describe intricate data formats in a concise manner. The XDR language is similar to the C language. Protocols such as RPC and the NFS use XDR to describe the format of their data. The XDR standard assumes that bytes (or octets) are portable and that a byte is defined to be 8 bits of data. Graphic Box NotationThis appendix uses graphic box notation for illustration and comparison. In most illustrations, each box depicts a byte. The representation of all items requires a multiple of four bytes (or 32 bits) of data. The bytes are numbered 0 through n-1. The bytes are read or written to some byte stream such that byte m always precedes byte m+1. The n bytes are followed by enough (0 to 3) residual zero bytes, r, to make the total byte count a multiple of four. Ellipses (...) between boxes show zero or more additional bytes where required. For example:
Basic Block SizeChoosing the XDR block size requires a trade off. Choosing a small size such as two makes the encoded data small, but causes alignment problems for machines that are not aligned on these boundaries. A large size such as eight means the data will be aligned on virtually every machine, but causes the encoded data to grow too large. Four was chosen as a compromise. Four is big enough to support most architectures efficiently, except for rare machines such as the eight-byte aligned Cray. This is not to say that the computers cannot utilize standard XDR, just that they do so at a greater overhead per data item than 4-byte (32-bit) architectures. Four is also small enough to keep the encoded data restricted to a reasonable size. The same data should encode into an equivalent result on all machines, so that encoded data can be compared or checksummed. So, variable length data must be padded with trailing zeros. XDR Data Type DeclarationsEach of the sections that follow:
For each data type in the language we show a general paradigm declaration. Note that angle brackets (< and >) denote variable length sequences of data and square brackets ([and]) denote fixed-length sequences of data. n, m and r denote integers. For the full language specification, refer to "The XDR Language Specification ". For some data types, specific examples are included. A more extensive example is given in the section, "XDR Data Description ". Signed IntegerDescriptionAn XDR signed integer is a 32-bit datum that encodes an integer in the range [-2147483648,2147483647]. The integer is represented in two's complement notation; the most and least significant bytes are 0 and 3, respectively. DeclarationIntegers are declared: int identifier; Encoding
Unsigned IntegerDescriptionAn XDR unsigned integer is a 32-bit datum that encodes a nonnegative integer in the range [0, 4294967295]. The integer is represented by an unsigned binary number whose most and least significant bytes are 0 and 3, respectively. DeclarationAn unsigned integer is declared as follows: unsigned int identifier; Encoding
EnumerationsDescriptionEnumerations have the same representation as signed integers and are handy for describing subsets of the integers. DeclarationEnumerated data is declared as follows: enum {name-identifier = constant, ... } identifier;
For example, an enumerated type could represent the three colors red, yellow, and blue as follows: enum {RED = 2, YELLOW = 3, BLUE = 5} colors;
It is an error to assign to an EncodingSee "Signed Integer". BooleansDescriptionBooleans are important enough and occur frequently enough to warrant their own explicit type in the standard. Booleans are integers of value 0 or 1. DeclarationBooleans are declared as follows: bool identifier; This is equivalent to: enum {FALSE = 0, TRUE = 1} identifier;
EncodingSee "Signed Integer". Hyper Integer and Unsigned Hyper IntegerDescriptionThe standard defines 64-bit (8-byte) numbers called DeclarationHyper integers are declared as follows: hyper int identifier; unsigned hyper int identifier; Encoding
Floating PointDescriptionThe standard defines the floating-point data type S: The sign of the number. Values 0 and 1 represent positive and negative, respectively. One bit. E: The exponent of the number, base 2. There are eight bits in this field. The exponent is biased by 127. F: The fractional part of the number's mantissa, base 2. There are 23 bits are in this field. Therefore, the floating-point number is described by: (-1)**S * 2**(E-Bias) * 1.F DeclarationSingle-precision floating-point data is declared as follows: float identifier; Double-precision floating-point data is declared as follows: double identifier; Encoding
![]() Just as the most and least significant bytes of an integer are 0 and 3, the most and least significant bits of a double-precision floating- point number are 0 and 63. The beginning bit (and most significant bit) offsets of S, E, and F are 0, 1, and 12, respectively. These offsets refer to the logical positions of the bits, not to their physical locations (which vary from medium to medium). The IEEE specifications should be consulted about the encoding for signed zero, signed infinity (overflow), and de-normalized numbers (underflow) [1]. According to IEEE specifications, the NaN (not a number) is system dependent and should not be used externally. Quadruple-Precision Floating PointDescriptionThe standard defines the encoding for the quadruple-precision floating-point data type S: The sign of the number. Values 0 and 1 represent positive and negative, respectively. One bit. E: The exponent of the number, base 2. There are 15 bits in this field. The exponent is biased by 16383. F: The fractional part of the number's mantissa, base 2. There are 111 bits in this field. Therefore, the floating-point number is described by: (-1)**S * 2**(E-Bias) * 1.F Declarationquadruple identifier; Encoding
![]() Just as the most and least significant bytes of an integer are 0 and 3, the most and least significant bits of a quadruple-precision floating- point number are 0 and 127. The beginning bit (and most significant bit) offsets of S, E, and F are 0, 1, and 16, respectively. These offsets refer to the logical positions of the bits, not to their physical locations (which vary from medium to medium). The IEEE specifications should be consulted about the encoding for signed zero, signed infinity (overflow), and de-normalized numbers (underflow) [1]. According to IEEE specifications, the NaN (not a number) is system dependent and should not be used externally. Fixed-Length Opaque DataDescriptionAt times, fixed-length uninterpreted data needs to be passed among machines. This data is called DeclarationOpaque data is declared as follows: opaque identifier[n]; where the constant n is the (static) number of bytes necessary to contain the opaque data.The n bytes are followed by enough (0 to 3) residual zero bytes, r, to make the total byte count of the opaque object a multiple of four. EncodingThe n bytes are followed by enough (0 to 3) residual zero bytes, r, to make the total byte count of the opaque object a multiple of four.
Variable-Length Opaque DataDescriptionThe standard also provides for variable-length (counted) opaque data, defined as a sequence of n (numbered 0 through n-1) arbitrary bytes to be the number n encoded as an unsigned integer (as described subsequently), and followed by the n bytes of the sequence. Byte b of the sequence always precedes byte b+1 of the sequence, and byte 0 of the sequence always follows the sequence's length (count). The n bytes are followed by enough (0 to 3) residual zero bytes, r, to make the total byte count a multiple of four. DeclarationVariable-length opaque data is declared in the following way: opaque identifier<m>; or opaque identifier<>;; The constant m denotes an upper bound of the number of bytes that the sequence may contain. If m is not specified, as in the second declaration, it is assumed to be (2**32) - 1, the maximum length. For example, a filing protocol may state that the maximum data transfer size is 8192 bytes, as follows: opaque filedata<8192>; Encoding
![]() It is an error to encode a length greater than the maximum described in the specification. Counted Byte StringsDescriptionThe standard defines a string of n (numbered 0 through n-1) ASCII bytes to be the number n encoded as an unsigned integer (as described previously), and followed by the n bytes of the string. Byte b of the string always precedes byte b+1 of the string, and byte 0 of the string always follows the string's length. The n bytes are followed by enough (0 to 3) residual zero bytes, r, to make the total byte count a multiple of four. DeclarationCounted byte strings are declared as follows: string object<m>; or string object<>; The constant m denotes an upper bound of the number of bytes that a string may contain. If m is not specified, as in the second declaration, it is assumed to be (2**32) - 1, the maximum length. The constant m would normally be found in a protocol specification. For example, a filing protocol may state that a file name can be no longer than 255 bytes, as follows: string filename<255>; Encoding
![]() It is an error to encode a length greater than the maximum described in the specification. Fixed-Length ArrayFixed-length arrays of elements numbered 0 through n-1 are encoded by individually encoding the elements of the array in their natural order, 0 through n-1. Each element's size is a multiple of four bytes. Though all elements are of the same type, the elements may have different sizes. For example, in a fixed-length array of strings, all elements are of type DeclarationDeclarations for fixed-length arrays of homogenous elements are in the following form: type-name identifier[n]; Encoding
Variable-Length ArrayDescriptionCounted arrays allow variable-length arrays to be encoded as homogeneous elements: the element count n (an unsigned integer) is followed by each array element, starting with element 0 and progressing through element n-1. DeclarationThe declaration for variable-length arrays follows this form: type-name identifier<m>; or type-name identifier<>; The constant m specifies the maximum acceptable element count of an array. If m is not specified, it is assumed to be (2**32) - 1. Encoding
![]() It is an error to encode a length greater than the maximum described in the specification. StructureDescriptionThe components of the structure are encoded in the order of their declaration in the structure. Each component's size is a multiple of four bytes, though the components may be different sizes. DeclarationStructures are declared as follows: struct {
component-declaration-A;
component-declaration-B;
...
} identifier;
Encoding
Discriminated UnionDescriptionA discriminated union is a type composed of a discriminant followed by a type selected from a set of prearranged types according to the value of the discriminant. The type of discriminant is either DeclarationDiscriminated unions are declared as follows: union switch (discriminant-declaration) {
case discriminant-value-A:
arm-declaration-A;
case discriminant-value-B:
arm-declaration-B;
...
default:
default-declaration;
} identifier;
Each case keyword is followed by a legal value of the discriminant. The default arm is optional. If it is not specified, then a valid encoding of the union cannot take on unspecified discriminant values. The size of the implied arm is always a multiple of four bytes. The discriminated union is encoded as its discriminant followed by the encoding of the implied arm. Encoding
VoidDescriptionAn XDR DeclarationThe declaration is simply as follows: void; ConstantDescription
The following example defines a symbolic constant DOZEN, equal to 12. const DOZEN = 12; DeclarationThe declaration of a constant follows this form: const name-identifier = n; Typedef
typedef declaration; The new type name is actually the variable name in the declaration part of the typedef egg eggbox[DOZEN]; Variables declared using the new type name have the same type as the new type name would have in the eggbox fresheggs; egg fresheggs[DOZEN]; When a typedef <<struct, union, or enum definition>> identifier; may be converted to the alternative form by removing the typedef enum {/* using typedef */
FALSE = 0,
TRUE = 1
} bool;
enum bool {/* preferred alternative */
FALSE = 0,
TRUE = 1
};
This syntax is preferred because one does not have to go to the end of a declaration to learn the name of the new type. Optional-DataOptional-data is one kind of union that occurs so frequently that it is given a special syntax of its own for declaring it. It is declared as follows: type-name *identifier; This is equivalent to the following union: union switch (bool opted) {
case TRUE:
type-name element;
case FALSE:
void;
} identifier;
It is also equivalent to the following variable-length array declaration, since the Boolean opted can be interpreted as the length of the array: type-name identifier<1>; Optional-data is useful for describing recursive data-structures, such as linked lists and trees. The XDR Language SpecificationNotational ConventionsThis specification uses a modified Backus-Naur Form notation for describing the XDR language. Here is a brief description of the notation:
Lexical Notes
Syntax Notes
XDR Data DescriptionHere is a short XDR data description of a file data structure, which might be used to transfer files from one machine to another. Example C-2 XDR File Data Structur
Suppose now that there is a user named john who wants to store his LISP program sillyprog that contains just the data "quit." His file would be encoded as follows: Table C-2 XDR Data Description Example
RPC Language ReferenceThe RPC language is an extension of the XDR language. The sole extension is the addition of the program and version types. For a description of the RPC extensions to the XDR language, see Appendix B, RPC Protocol and Language Specification. The RPC language is similar to C. This section describes the syntax of the RPC language, showing a few examples along the way. It also shows how RPC and XDR type definitions get compiled into C type definitions in the output header file. An RPC language file consists of a series of definitions. definition-list: definition; definition; definition-list It recognizes six types of definitions. definition: enum-definition const-definition typedef-definition struct-definition union-definition program-definition Definitions are not the same as declarations. No space is allocated by a definition - only the type definition of a single or series of data elements. This means that variables still must be declared. EnumerationsRPC/XDR enumerations have similar 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
Here is an example of an XDR enum and the C enum to which it gets compiled.
enum colortype { enum colortype {
RED = 0, RED = 0,
GREEN = 1, --> GREEN = 1,
BLUE = 2 BLUE = 2,
}; };
typedef enum colortype colortype;
ConstantsXDR symbolic constants may be used wherever an integer constant is used. For example, in array size specifications: const-definition: const const-ident = integer The following example defines a constant, DOZEN as equal to 12: const DOZEN = 12; --> #define DOZEN 12 Type DefinitionsXDR typedef-definition: typedef declaration This example defines an typedef string fname_type<255>; --> typedef char *fname_type; DeclarationsIn XDR, there are four kinds of declarations. These declarations must be a part of a declaration: simple-declaration fixed-array-declaration variable-array-declaration pointer-declaration Simple DeclarationsSimple declarations are just like simple C declarations: simple-declaration: type-ident variable-ident Example: colortype color; --> colortype color; Fixed-Length Array DeclarationsFixed-length array declarations are just like C array declarations: fixed-array-declaration: type-ident variable-ident [value] Example: colortype palette[8]; --> colortype palette[8]; Many programmers confuse variable declarations with type declarations. It is important to note that rpcgen does not support variable declarations. This example is a program that will not compile: int data[10];
program P {
version V {
int PROC(data) = 1;
} = 1;
} = 0x200000;
The example above will not compile because of the variable declaration: int data[10] Instead, use: typedef int data[10]; or struct data {int dummy [10]};
Variable-Length Array DeclarationsVariable-length array declarations have no explicit syntax in C. The XDR language does have a syntax, using angle brackets: variable-array-declaration: type-ident variable-ident <value> type-ident variable-ident < > The maximum size is specified between the angle brackets. The size may be omitted, indicating that the array may be of any size: int heights<12>; /* at most 12 items */ int widths<>; /* any number of items */ Because variable-length arrays have no explicit syntax in C, these declarations are compiled into struct {
u_int heights_len; /* # of items in array */
int *heights_val; /* pointer to array */
} heights;
The number of items in the array is stored in the _len component and the pointer to the array is stored in the _val component. The first part of each component name is the same as the name of the declared XDR variable (heights). Pointer DeclarationsPointer declarations are made in XDR exactly as they are in C. Address pointers are not really sent over the network; instead, XDR pointers are useful for sending recursive data types such as lists and trees. The type is called "optional-data," not "pointer," in XDR language: pointer-declaration: type-ident *variable-ident Example: listitem *next; --> listitem *next; StructuresAn RPC/XDR struct-definition:
struct struct-ident "{"
declaration-list
"}"
declaration-list:
declaration ";"
declaration ";" declaration-list
The following XDR structure is an example of a two-dimensional coordinate and the C structure that it compiles into: struct coord { struct coord {
int x; --> int x;
int y; int y;
}; };
typedef struct coord coord;
The output is identical to the input, except for the added UnionsXDR unions are discriminated unions, and do not look like C unions - they are more similar to Pascal variant records: union-definition:
"union" union-ident "switch" "("simple declaration")" "{"
case-list
"}"
case-list:
"case" value ":" declaration ";"
"case" value ":" declaration ";" case-list
"default" ":" declaration ";"
The following is an example of a type returned as the result of a "read data" operation: If there is no error, return a block of data; otherwise, don't return anything. union read_result switch (int errno) {
case 0:
opaque data[1024];
default:
void;
};
It compiles into the following: struct read_result {
int errno;
union {
char data[1024];
} read_result_u;
};
typedef struct read_result read_result;
Notice that the union component of the output struct has the same name as the type name, except for the trailing _u. ProgramsRPC 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;
When the -N option is specified, rpcgen also recognizes the following syntax: procedure:
type-ident procedure-ident "(" type-ident-list ")" "=" value;
type-ident-list:
type-ident
type-ident "," type-ident-list
For example: /*
* time.x: Get or set the time. Time is represented as seconds
* since 0:00, January 1, 1970.
*/
program TIMEPROG {
version TIMEVERS {
unsigned int TIMEGET(void) = 1;
void TIMESET(unsigned) = 2;
} = 1;
} = 0x20000044;
Note that the This file compiles into these #define statements in the output header file: #define TIMEPROG 0x20000044 #define TIMEVERS 1 #define TIMEGET 1 #define TIMESET 2 Special CasesThere are several exceptions to the RPC language rules. C-style ModeIn the new features section we talked about the features of the C-style mode of rpcgen. These features have implications with regard to the passing of BooleansC has no built-in Example: bool married; --> bool_t married; StringsThe C language has no built-in In XDR language, strings are declared using the Examples: string name<32>; --> char *name; string longname<>; --> char *longname; Note -
NULL Opaque DataOpaque data is used in XDR to describe untyped data, that is, sequences of arbitrary bytes. It may be declared either as a fixed length or variable length array. Examples: opaque diskblock[512]; --> char diskblock[512];
opaque filedata<1024>; --> struct {
u_int filedata_len;
char *filedata_val;
} filedata;
VoidsIn a |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||