File: procdef.ml

package info (click to toggle)
camlrpc 0.4.1-7
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 1,080 kB
  • ctags: 1,474
  • sloc: ml: 11,901; makefile: 592; sh: 345; ansic: 331
file content (147 lines) | stat: -rw-r--r-- 5,811 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
(* Definitions of the procedures:
 *
 * Unlike the typical C implementations, there is no separate interface
 * definition file. This is because O'Caml is powerful enough to 
 * express all necessary information itself.
 *
 * The procedures have all a function type s -> t, where s and t are
 * valid XDR types. XDR or "external data representation" is the way
 * argument and result values are passed from the client to the server
 * and vice versa. XDR defines a value space and a representation on
 * bit level that must be used to form octet sequences that are
 * valid RPC messages. The value space is typed.
 *
 * To have a more convenient method to write down the type terms for
 * s and t, it is possible to have type abbreviations, i.e. additional
 * identifiers that expand to whole type terms. These abbreviations 
 * can depend on earlier abbreviations, and because of this they
 * are defined as a "type system".
 *
 * So the steps defining the procedures are:
 * 
 * STEP 1: Define necessary type names using a "type system".
 * STEP 2: Define the "program", i.e. the set of procedures and their
 *         signatures. The type names from step 1 can be used.
 *
 * The rest depends on what should be done with that definitions. For
 * RPC clients, the "program" suffices to define a "client". For servers,
 * there must be an additional binding to real O'Caml functions.
 *
 * FURTHER READING:
 *
 * - See the xdr.mli definition on the concepts around the "external
 *   data representation", such as XDR types and type systems.
 * - See the Rpc_program.mli definition for more about programs.
 * - See rtypes.mli about true 32 and 64 bit integers
 *)

open Xdr
open Rtypes

(* STEP 1 *)

let unvalidated_type_system =
  [ "stringlist",      X_rec("recvar",
			     x_optional ( X_struct [ "value", x_string_max;
						     "next",  X_refer "recvar"
						   ] ));

       (* "stringlist" is an abbreviation for the type on the right side.
	* This type is rather complicated as it is recursive. The X_rec
	* marks the beginning of the recursion, and the X_refer refers to
	* the definition; both use a variable "recvar" which simply says
	* which X_refer refers to which X_rec if you have more than one
	* recursion. x_optional is a function, not a value constructor,
	* and x_optional t expands to
	*   X_union_over_enum (x_bool, ["TRUE", t; "FALSE", X_void], None)
	* meaning a union of t and X_void discriminated by a boolean --
	* this is the same as the 'option' type in O'Caml and because of
	* this I called the function 'x_optional'. (Traditionally, RPC
	* implementations call this a 'pointer' because it is often used
	* where C demands a pointer type.)
	* The X_struct is a ordered tuple with named components, i.e. a
	* record type in O'Caml.
        * The x_string_max is a string of arbitrary length with arbitrary
	* contents of octets (i.e. even 0-characters are allowed, this
	* is not a C string).
	* As you see, the XDR types have value semantics just as the
	* core O'Caml types. The reason for this is that such types are
	* simpler to serialize, i.e. pack as octet sequences. The disadvantage
	* is that you can at most define trees, for more general structures
	* you would have to introduce reference semantics by the back door
	* ('handles', 'descriptors' and so on).
	* The corresponding O'Caml definition for a "stringlist" would
	* be:
	*
	* type stringlist_struct = { value : string; next : stringlist }
	*  and stringlist = stringlist_struct option
	*
        * or just "string list", of course.
	*
	* Examples for values being compatible with "stringlist":
	* - XV_union_over_enum ("FALSE", XV_void)
	*   the empty list
	* - XV_union_over_enum ("TRUE", 
	*                       XV_struct [ "value", 
	*                                          XV_string "Hello";
        *                                   "next", 
        *                                          XV_union_over_enum ("FALSE", 
        *                                                             XV_void));
	*                                 ])
        *  the list [ "Hello" ]
	*)

    "stringarray",         X_array (x_string_max, uint4_of_int 100);

       (* This is an array of string with at most 100 elements. *)

  ] ;;


let type_system = validate_xdr_type_system unvalidated_type_system;;
  (* validate_xdr_type_system: does some checks on the consistency
   * of the definition and expands all X_type constructs.
   *)


(* STEP 2 *)

let program =
  Rpc_program.create

    (uint4_of_int 0x20000111)   (* the program number *)
    (uint4_of_int 1)            (* the version number *)

              (* All programs have 32 bit program numbers. These should
	       * uniquely identify the type of RPC service.
	       * range 0x0        to 0x1fffffff: defined by Sun Microsystems
	       * range 0x20000000 to 0x3fffffff: defined by the local admin
	       * range 0x40000000 to 0x5fffffff: for dynamically generates nrs
	       * all other:                      reserved
	       *)

    type_system

    [ "plus1", (uint4_of_int 1, X_int, X_int);

            (* procedure "plus1": computes the passed argument + 1.
	     * This is procedure number 1. Its argument type is X_int, the
	     * result type is X_int, too.
	     * Note: X_int are signed 32 bit integers.
	     *)

      "sortlist", (uint4_of_int 2, X_type "stringlist", X_type "stringlist");

            (* procedure "sortlist": Sorts the given list of strings.
	     * This is procedure number 2. Both argument and result type
	     * use the type named "stringlist" defined in the 'type_system'.
	     *)

      "sortarray", (uint4_of_int 3, X_type "stringarray", X_type "stringarray");

            (* procedure "sortarray": Sorts the given array of strings.
	     * This is procedure number 3.
	     *)
    ] 
;;