Example Protocol


Detailed Description

Protocol-dependent API for an example protocol.

Much of the miniRPC interface is specific to the application protocol being implemented on top of miniRPC. The code to implement this interface is generated by minirpcgen from a ".mx" or protocol definition file. This documentation will illustrate the protocol-dependent interfaces using a simple example protocol.

A protocol definition file describes the data structures and procedure calls to be supported by the protocol. The data structures are defined using XDRL, the External Data Representation Language, defined in RFC 4506. The procedure calls are defined using a syntax specific to miniRPC.

First, we examine the protocol definition for our example protocol.

The example.mx File

enum example_color {
        RED = 0,
        ORANGE = 1,
        YELLOW = 2,
        GREEN = 3,
        BLUE = 4,
        INDIGO = 5,
        VIOLET = 6
};

struct example_color_choice {
        enum example_color acceptable<>;
        enum example_color preferred;
};

The example protocol starts out by defining an example_color enumeration, and then defines an example_color_choice structure which will be used as the basis of a protocol message. example_color_choice contains a variable-length array of "acceptable" colors, and one particular color which is selected as "preferred".

typedef int example_count;

miniRPC presently does not support the use of primitive XDR types as request or reply arguments to RPC procedures. A procedure argument must be a named type corresponding to a struct, enum, or typedef, or must be void. As here, if a protocol needs to use a primitive type as a procedure argument, it must declare and use a typedef for that type.

serverprocs {
        choose_color(example_color_choice) = 1;
        get_num_colors(void, example_count) = 2;
}

We now define the procedure calls to be supported by the server. Each procedure can have up to two arguments: one request argument and one reply argument, in that order. Unused arguments can be omitted from the procedure definition or declared to be void. As with get_num_colors, a procedure with a reply argument but no request argument must declare the request argument to be void. Each procedure is also assigned a procedure number, which is used by the protocol to indicate which procedure is being called.

Since these procedures are declared in a serverprocs section, they are procedure calls made from client to server; that is, the client is the sender and the server is the receiver. There can also be a clientprocs section, which defines procedure calls initiated by the server and received by the client.

No two procedures in a protocol can have the same name. No two procedures of the same type (serverprocs, clientprocs, servermsgs, or clientmsgs) can have the same procedure number.

servermsgs {
        crayon_selected(example_color) = 1;
}

This protocol includes an additional crayon_selected message, which is not really a procedure call at all: it is an event notification sent from client to server, to which the server has no opportunity to reply. (Procedure calls declared in a procs section with a void return type, such as choose_color above, still involve a reply, since the receiver can return a success indication or error code.) Accordingly, procedure definitions in the msgs section take only a request argument.

As above, messages sent from client to server are defined in a servermsgs section, and messages sent by the server are defined in a clientmsgs section.

Generating the Protocol Interface

This interface definition is converted into C source and header files by running:

minirpcgen -o example example.mx

The result is a set of output files:

The C source files should be compiled into the programs implementing the client and server (either directly, or indirectly via a library). The header files should also be made available to these programs during their build process. A client application implementing this example protocol need only include example_client.h directly; likewise, a server need only include example_server.h.

Note that the argument given to minirpcgen's -o option is embedded not only in the names of the output files, but in the names of the generated miniRPC structures and C functions. (This does not apply to the XDR structs and enums specified in the .mx file.) If the -o option is not specified, the name of the .mx file (with ".mx" removed) is used.

Note:
If your project uses Make, note that subtle build races can occur when one Makefile target updates several outputs at once and several make jobs are run in parallel (e.g., with "make -j3"). If you use GNU Make, you can use pattern rules to properly handle this case:

%_minirpc.c %_minirpc.h %_client.h %_server.h %_xdr.c %_xdr.h: %.mx
	$(MINIRPCGEN) $^
For more information on the interface generated by minirpcgen, see Common Definitions, Client Stubs, and Server Stubs. For example code using this protocol, see Example Client Program and Example Server Program.

Advanced minirpcgen

Compile Passes

minirpcgen generates output in three passes. The *_xdr.c and *_xdr.h files are generated by the rpcgen program in two separate passes; the rest of the output files are generated by minirpcgen itself.

As a result, parse errors may be issued at several points in the compile process. minirpcgen itself will issue errors relating to procedure definition blocks, while rpcgen will issue errors relating to XDR data type definitions. rpcgen does not attempt to catch all type definition errors directly, so some errors may only appear once the C compiler attempts to compile the generated code.

Using cpp

.mx files are preprocessed using cpp before they are read, so all of the usual preprocessor directives (#include, etc.) work as expected. minirpcgen defines special preprocessor macros during each pass over the input file:

For the XDR passes only, you can embed literal strings in the output files by prefixing them with "%". Using both literal strings and defines it is possible to declare common data structures in a .mx file and include it into several others with the following fragment:

#ifdef MINIRPC
#include "common.mx"
#else
%#include "common_xdr.h"
#endif

You can define additional preprocessor macros by passing "-D MACRONAME=value" to minirpcgen. Multiple -D options are accepted.


Modules

 Common Definitions
 Client Stubs
 Server Stubs


miniRPC 0.3.3
Documentation generated by Doxygen 1.5.6