Distributed Interface - Reference Manual Description This document will provide essential information for those wishing to use the DCE group's services in distributing an interface. This document does not attempt to explain all of the complexities involved in setting up and making the actual DCE remote procedure calls. The DCE group will be writing wrapper functions that hide most of those details. Nonetheless, certain facets of DCE RPC must shine through and it is important that the user of the wrapper functions understand the limitations of remote procedure calls. By following the procedures herein, an individual will help ensure that his/her code will comply with the requirements specified by DCE RPC and with the method of interface distribution currently supported by the DCE group. Process The client of these services (an individual or programming team hereafter referred to as the user) will produce an interface which is a list of completely specified C function prototypes. They will also implement the functions and test them in a normal manner. Correctness of the implementation should be completed before any attempt to build a distributed version of the interface. This will greatly ease any troubleshooting that may arise when the functions are called remotely. The DCE group will receive the interface and the implementation, review the correctness of the interface in light of RPC requirements, and then provide both client and server modules. The client module will consist of local wrapper functions that may be compiled and linked with any other code that runs on the client side. The user will use these functions as if they were simple local calls. The server module will consist of an executable, ready to be run on the server host. The DCE group will build the server executable once all functions for the interface are specified and implemented. The result is a distributed interface that follows the client/server paradigm. The server runs in one process, waiting for requests from clients. Clients run in some other process (on the same or on a different machine) and issue local function calls that automatically connect to the server. The transport of the function call with its parameters and return values is transparent to the caller of the function. Requirements The prototype of a remote procedure call has some additional constraints compared to local function calls in C. These are a result of the requirement to marshal the parameters (and return types) to the functions for transport across the network. Therefore, the parameters to a remote procedure call must conform to those data types available in OSF DCE. Also, to help maintain a consistent use of distributed interfaces, the DCE group has recommended a standard use of function return types and out parameters. Finally, additional information must be provided to allow DCE runtime to locate the server. These three constraints will be discussed separately. (1) Data Types Simple (non-composite) data types may be easily transported across the network as parameters or return values. DCE will handle all conversions between hosts of differing representation (this is called marshaling). DCE provides specific types to guarantee the marshaling is performed correctly. Some of these are shown in the table below. IDL Data Type Size (bits) short int 16 long int 32 unsigned short int 16 unsigned long int 32 float 32 double 64 char 8 boolean 8 byte 8 Of particular interest is the byte type which is not marshaled. This means that the bit sequence is unchanged during transmission, regardless of the platforms involved. Therefore, an array of this type would be appropriate for a bit-stream. Fixed arrays or structures of any of these types may be used as parameters or return values without special consideration. Variable length arrays require resolution of the length of the array at the time the function is called. This is done by adding an additional parameter (of integer type) to the function that describes the length of the array (see example). Strings are normally stored in fixed length arrays and may be handled the same way. If necessary, a special identifier ([string]) will cause DCE to transport only those elements of the array preceding the null character termination byte or, if no termination character is found, all the characters in the array. Pointers provide additional complexity in a distributed environment because memory is not shared between the client and the server. However, they are useful as out parameters. In order to use a pointer as an out type, it must point to allocated storage of a known type. Furthermore, the pointer itself must not change during the function call and it may not be used as an alias to some data elements already used by the function. In general, using pointers will not increase performance in DCE because the parameters are always copied into the stub before they are marshaled. For this reason and because of the additional complexity, they should only be used for out types. Finally, every parameter must be defined as in, out, or in/out. This tells DCE which way the data is flowing on the network and allows packet size to be optimized. (2) Return Values & Out Parameters Often, the return value of a C function will be used to return the desired output of the function. An alternate method is to use out parameters (pointers) in the parameter list. The DCE group has standardized on the latter to allow multiple return values and facilitate separate error status return. Therefore, all functions that are intended to be called remotely should return an int which will be reserved for use as error status. The definition of errors is TBD. Any values to be returned by the function itself should be specified as out parameters. The caller of the function should allocate the space the pointer references. (3) Binding Handles In order to complete a remote procedure call, a server that offers the required interface (remote function service) must be found. In OSF DCE there are many ways of accomplishing this, but in our installation we have verified only two: string binding and endpoint mapping. The former requires the caller of the function to know everything about the location of the server, including the port number which changes every time the server is run. Without any way of finding that port number at run time except through direct user intervention, this method is quite impractical. Endpoint mapping allows the port to be automatically determined at runtime which greatly eases making a connection. The only information required by endpoint mapping is the network protocol and the name of the server. At this stage of development, only the UDP protocol is reliable. Therefore, the user must add only one parameter to the function to connect to the correct server: the server's name. This may be provided as a name or as an IP address. Example Below are some examples which further clarifies the syntax: // typdefs for parameter types typedef [string] char name_t[15]; // a string as a fixed length array typedef char ssn_t[11]; // a fixed length array typedef struct { // a struct name_t name; ssn_t ssn; } person_t; typedef person_t people[]; // a variable length array // sample function prototypes int get_id( // function using simple in [in] handle h, [in] name_t name, // and out parameters [out] ssn_t *ssn); int get_contacts( // function using composite and [in] handle h, // variable length parameters [in] person_t person, [out] int *num_people, // note: num_people describes the [out] people_t *people); // length of variable array people // a call to get_id: get_id("boa", my_name, &my_ssn); // a call to get_contacts: get_contacts("129.65.54.17", a_person, &num_p, &p); Conclusion This document has described some important considerations to keep in mind while developing an interface that is intended to be distributed via OSF DCE. Additionally, this document clarifies some of the interface standards that the DCE group intends to use. Our interface as described is based on currently verified DCE functionality running on the HP's. This is only a limited set of the functionality provided by OSF DCE. Presently, we are constrained by an incomplete installation of OSF DCE and by time. Some of the other capabilities of DCE that are not represented in this document are: *cell directory service - allows automatic lookup of host name *multi-threaded servers - allows multiple simultaneous clients to connect to a single server and allows the server to perform other activities while waiting for client calls *pipes - provides stream type communications between clients and servers *full pointers - allows transmission of linked lists, etc. These functions will be provided as the installation evolves and as the core knowledge of the DCE team grows.