[Top] [Prev] [Next] [Bottom]

4. Building RPC Client and Server Programs


Introduction

This chapter deals with building client and server programs using the IDL stubs.

Prerequisite Knowledge

The BEA TUXEDO TxRPC programmer should be familiar with the C compilation system and building BEA TUXEDO clients and servers. Building BEA TUXEDO clients and servers is covered in the BEA TUXEDO Programmer's Guide. Building workstation clients is covered in the BEA TUXEDO Workstation Guide.

Building an RPC Server

RPC servers are built and configured in much that same way that ATMI Request/Response servers are. In fact, the service name space for RPC and Request/Response servers is the same. However, the names advertised for RPC services are different. For Request/Response servers, a service name is mapped to a procedure. For RPC servers, a service name is mapped to an IDL interface name. The RPC service advertised will be <interface>v<major>_<minor>, where <interface> is the interface name, and <major> and <minor> are the major and minor numbers of the version, as specified (or defaulted to 0.0) in the interface definition. Because the service name is limited to 15 characters, this limits the length of the interface name to 13 characters minus the number of digits in the major and minor version numbers. This also implies that an exact match is used on major AND minor version numbers because of the way name serving is done in the BEA TUXEDO system. Note that the interface, and not individual operations, are advertised (similar to DCE/RPC). The server stub automatically takes care of calling the correct operation within the interface.

RPC servers are built using the buildserver command. We recommend using the -s option to specify the service (interface) names at compilation time. The server can then be booted using the -A option to get the services automatically advertised. This approach is used in the sample application, as shown in Appendix A, "A Sample Application."

The buildserver command automatically links in the BEA TUXEDO libraries. However, the RPC runtime must be linked in explicitly. This is done by specifying the -f -ltrpc option after any application files on the buildserver line. Normally, the output of the tidl command is a server stub object file. This can be passed directly to the buildserver command. Note that the server stub and the application source, object, and library files implementing the operations should be specified ahead of the runtime library, also using the -f option. See the makefile rpcsimp.mk, in Appendix A, "A Sample Application," for an example.

Building an RPC Client

A native RPC client is built using the buildclient command. This command automatically links in the BEA TUXEDO libraries. However, the RPC runtime must be linked in explicitly. This is done by specifying the -f -ltrpc option after any application files on the buildclient command line. Normally, the output of the tidl command is a client stub object file. This can be passed directly to the buildclient command. Note that the client stub and the application source, object, and library files executing the remote procedure calls should be specified ahead of the runtime library, also using the -f option. For an example, see the makefile rpcsimp.mk in Appendix A, "A Sample Application."

To build a UNIX Workstation client, simply add the -w option to the buildclient command line so that the Workstation libraries are linked in instead of the native libraries.

Building a DOS Workstation RPC Client

On DOS, the tidl command does not generate object files (due to memory limitations). The output of tidl is simply the C source file for the client stub. Like any application source files, the source file for the client stub must be compiled to an object file using a compiler in the DOS environment. Remember to use the same memory model when compiling each of the object files. Another thing to watch out for in this environment is that file names are limited to 8 characters (with 3 for extension). It may be necessary to use the -cstub option to specify the output file name for the stub file. A DOS RPC client is built using the buildclt command, specifying the appropriate memory model. This command automatically links in the BEA TUXEDO System Workstation libraries. However, the RPC runtime must be linked in explicitly. This is done by specifying the -f ltrpc.lib option after any application object files on the buildclt command line (the library for the medium memory model is mtrpc.lib). Note that the client stub and the application source, object, and library files executing the remote procedure calls should be specified ahead of the runtime library, also using the -f option. For an example, see the makefile rpcsimp.mak in Appendix A, "A Sample Application."

Building a Windows Workstation RPC Client

Compilation of the client stub for Windows is similar to the DOS compilation, but requires the -D_TM_WIN definition as a compilation option. This ensures that the correct function prototypes for the TxRPC and BEA TUXEDO system runtime functions are used. While the client stub source is the same, it must be compiled specially to handle the fact that the text and data segments for the DLL will be different from the code calling it. The header file and stub are automatically generated to allow for the declarations to be changed easily, using C pre-processor definitions. The definition _TMF (for "far") appears before all pointers in the header file and _TMF is automatically defined as "_far" if _TM_WIN is defined.

In most cases, using standard libraries, the buildclt command can be used to link the client, and the -W option must be specified (for Windows). The library to be used is wtrpc.lib. Appendix A, "A Sample Application," shows a case where buildclt cannot be used because non-standard (QuickWin) libraries are being used.

The sample also shows how to create a Dynamic Link Library (DLL) using the client stub. This usage will be very popular when used with a visual application builder that requires DLL use (where the application code cannot be statically linked in). Windows functions are traditionally declared to have the _pascal calling convention. The header file and stub are automatically generated to allow for the declarations to be changed easily, using C pre-processor definitions. _TMX (for "eXport") appears before all declared functions. By default, this definition is defined to nothing. When compiling a stub for inclusion in a DLL, _TMX should be defined to _far _pascal. Also, the files to be included in the DLL must be compiled with the large memory model. Since using _pascal automatically converts the function names to upper case in the library, it is a good idea to run with the -port case option turned on, which does additional validation to see if two declared names differ only in case.

A complete example of building a Windows DLL is shown in Appendix A, "A Sample Application."

Note: A compilation error may occur if a TxRPC client includes windows.h, due to a duplicate uuid_t definition. It will be necessary for the application to either not include windows.h (because it is included already) or to include it within a different file in the application.

Building an OS/2 Workstation RPC Client

Compilation of OS/2 clients is similar to that for DOS or Windows clients. However, the -D_TM_OS2 option must be specified when compiling for OS/2. The library to be used is otrpc.lib for character mode OS/2 and ptrpc.lib for use with Presentation Manager. As in the case of Windows, all pointers in data structures and parameters are treated as far (4-byte) pointers.

Using C++

Clients and servers can be built using C or C++, interchangeably. The header files and generated stub source files are defined in such a way that all Stub Support functions and generated operations allow for complete interoperability between C++ and C. They are declared with C linkage, that is, as extern "C," so that name mangling is turned off.

The stub object files can be built using C++ by specifying CC -c for the -cc_cmd option of tidl. The CC command can be used to compile and link client and server programs by setting and exporting the CC environment variable before running buildclientand buildserver. For example:

tidl -cc_cmd "CC -c" -keep all t.idl
CC=CC buildserver -o server -s tv1_0 -f "-I. t_sstub.o server.c -ltrpc"

In the DOS, Windows, and OS/2 environments, C++ compilation is normally accomplished via a flag on the compilation command line or a configuration option rather than a different command name. Use the appropriate options to get C++ compilation.

Interoperability with DCE/RPC

The BEA TUXEDO TxRPC compiler uses the same IDL interface as OSF/DCE but the generated stubs do not use the same protocol. Thus, a BEA TUXEDO TxRPC stub cannot directly communicate with a stub generated by the DCE IDL compiler.

However, it is possible to have the following interoperations between DCE/RPC and BEA TUXEDO TxRPC:

The following sections show possible interactions between BEA TUXEDO TxRPC and OSF/DCE. In each case, the originator of the request is called the requester. This term is used instead of "client" because the requester could, in fact, be a DCE or BEA TUXEDO service making a request of another service. The terms "client" and "server" refer to the client and server stubs generated by the IDL compilers (either DCE idl(1) or BEA TUXEDO tidl(1)); these terms are used for consistency with the DCE and TxRPC terminology. Finally, the term "application service" is used for the application code that implements the procedure that is being called remotely (it is generally transparent whether the invoking software is the server stub generated by DCE or BEA TUXEDO).

BEA TUXEDO Requester to DCE Service via BEA TUXEDO Gateway

Figure 4-1 BEA TUXEDO Requester to DCE Service via BEA TUXEDO Gateway

The first approach uses a "gateway" such that the BEA TUXEDO client stub invokes a BEA TUXEDO server stub, via TxRPC, that has a DCE client stub linked in (instead of the application services) that invokes the DCE services, via DCE RPC. The advantage to this approach is that it is not necessary to have DCE on the client platform (e.g., in the case of NETWARE or Workstation platforms such as DOS). In fact, the set of machines running BEA TUXEDO and the set of machines running DCE could be disjoint except for one machine where all such gateways are running. This also provides a migration path with the ability to move services between BEA TUXEDO and DCE.

A sample application that implements this approach is described in Appendix B, "A DCE-Gateway Application."

In this configuration, the requester is built as a normal BEA TUXEDO client or server. Similarly, the server is built as a normal DCE server. The additional step is to build the gateway process which acts as a BEA TUXEDO server using a TxRPC server stub and a DCE client using a DCE/RPC client stub.

The process of running the two IDL compilers and linking the resultant files is simplified with the use of the blds_dce(1) command, which builds a BEA TUXEDO server with DCE linked in.

The usage for blds_dce is as follows.

blds_dce [-o output_file] [-i idl_options] [-f firstfiles] [-l lastfile] \
[idl_file . . . ]

The command takes as input one or more IDL files so that the gateway can handle one or more interfaces. For each one of these files, tidl is run to generate a server stub and idl is run to generate a client stub.

This command knows about various DCE environments and provides the necessary compilation flags and DCE libraries for compilation and linking. If you are developing in a new environment, it may be necessary to modify the command to add the options and libraries for your environment.

This command compiles the source files in such a way (with -DTMDCEGW defined) that memory allocation is always done using rpc_ss_allocate(3c) and rpc_ss_free(3c). This ensures that memory is freed on return from the BEA TUXEDO server. The use of -DTMDCEGW also includes DCE header files instead of BEA TUXEDO TxRPC header files.

The IDL output object files are compiled, optionally with specified application files (using the -f and -l options), to generate a BEA TUXEDO server using buildserver(1). The name of the executable server can be specified with the -o option.

When running this configuration, the DCE server would be started first in the background, then the BEA TUXEDO configuration including the DCE gateway would be booted, and then the requester would be run. Note that the DCE gateway is single-threaded so you will need to configure and boot as many gateway servers as you want concurrently executing services.

There are several optional things to consider when building this gateway.

Setting the DCE Login Context

First, as a DCE client, it is normal that the process runs as some DCE principal. There are two approaches to getting a login context. One approach is to "log in" to DCE. In some environments, this occurs simply by virtue of logging into the operating system. In many environments, it requires running dce_login. If the BEA TUXEDO server is booted on the local machine, then it is possible to run dce_login, then run tmboot(1) and the booted server will inherit the login context. If the server is to be booted on a remote machine which is done indirectly via tlisten(1), it is necessary to run dce_login before starting tlisten. In each of these cases, all servers booted in the session will be run by the same principal. The other drawback to this approach is that the credentials will eventually expire.

The other alternative is to have the process set up and maintain its own login context. The tpsvrinit(3c) function provided for the server can set up the context and then start a thread that will refresh the login context before it expires. Sample code to do this is provided in $TUXDIR/lib/dceserver.c; it must be compiled with the -DTPSVRINIT option to generate a simple tpsvrinit function. (It can also be used as the main() for a DCE server, as described in the following section.) This code is described in further detail in Appendix B, "A DCE-Gateway Application."

Using DCE Binding Handles

BEA TUXEDO TxRPC does not support binding handles. When sending an RPC from the requester's client stub to the server stub within the gateway, the BEA TUXEDO system handles all of the name resolution and choosing the server, doing load balancing between available servers. However, when going from the gateway to the DCE server, it is possible to use DCE binding. If this is done, it is recommended that two versions of the IDL file be used in the same directory or that two different directories be used to build the requester, and the gateway and server. The former approach of using two different file names is shown in the example with the IDL file linked to a second name. In the initial IDL file, no binding handles or binding attributes are specified. With the second IDL file, which is used to generate the gateway and DCE server, there is an associated ACF file that specifies [explicit_handle] such that a binding handle is inserted as the first parameter of the operation. From the BEA TUXEDO server stub in the gateway, a NULL handle will be generated (because handles aren't supported). That means that somewhere between the BEA TUXEDO server stub and the DCE client stub in the gateway, a valid binding handle must be generated.

This can be done by making use of the manager entry point vector. By default, the IDL compiler defines a structure with a function pointer prototype for each operation in the interface, and defines and initializes a structure variable with default function names based on the operation names. The structure is defined as

<INTERF>_v<major>_<minor>_epv_t<INTERF>_v<major>_<minor>_s_epv 

where <INTERF> is the interface name and <major>.<minor> is the interface version. This variable is dereferenced when calling the server stub functions. The IDL compiler option, -no_mepv, inhibits the definition and initialization of this variable, allowing the application to provide it in cases where there is a conflict or difference in function names and operation names. In the case where an application wants to provide explicit or implicit binding instead of automatic binding, the -no_mepv option can be specified, and the application can provide a structure definition that points to functions taking the same parameters as the operations but different (or static) names. The functions can then create a valid binding handle that is passed, either explicitly or implicitly, to the DCE/RPC client stub functions (using the actual operation names).

This is shown in the example in Appendix B, "A DCE-Gateway Application." The file dcebind.c generates the binding handle, and the entry point vector and associated functions are shown in dceepv.c.

Note that to specify the -no_mepv option when using the blds_dce, the -i -no_mepv option must be specified so that the option is passed through to the IDL compiler. This is shown in the makefile, rpcsimp.mk, in Appendix B, "A DCE-Gateway Application."

Authenticated RPC

Now that we have a login context and a handle, it is possible to use authenticated RPC calls. As part of setting up the binding handle, it is also possible to annotate the binding handle for authentication by calling rpc_binding_set_auth_info(). This is shown as part of generating the binding handle in dcebind.c in Appendix B, "A DCE-Gateway Application." This sets up the authentication (and potentially encryption) between the gateway and the DCE server. If the requester is a BEA TUXEDO server, then it is guaranteed to be running as the BEA TUXEDO administrator. For more information about authentication for BEA TUXEDO clients, see Administering the BEA TUXEDO System.

Transactions

OSF/DCE does not support transactions. That means that if the gateway is running in a group with a resource manager and the RPC comes into the BEA TUXEDO client stub in transaction mode, the transaction will not carray to the DCE server. There is not much you can do to solve this; just be aware of it.

DCE Requester to BEA TUXEDO Service Using BEA TUXEDO Gateway

Figure 4-2 DCE Requester to BEA TUXEDO Service Using BEA TUXEDO Gateway

In this figure, the DCE requester uses a DCE client stub to invoke a DCE service which calls the BEA TUXEDO client stub (instead of the application services), which invokes the BEA TUXEDO service (via TxRPC). Note that in this configuration, the client has complete control over the DCE binding and authentication. The fact that the application programmer builds the middle server means that the application also controls the binding of the DCE server to BEA TUXEDO service. This approach would be used in the case where the DCE requester does not want to directly link in and call the BEA TUXEDO system.

The main() for the DCE server should be based on the code provided in $TUXDIR/lib/dceserver.c. If you already have your own template for the main() of a DCE server, there are a few things that may need to be added or modified.

First, tpinit(3c) should be called to join the BEA TUXEDO application. If application security is configured, then additional information may be needed in the TPINIT buffer such as the user name and application password. Prior to exiting, tpterm(3c) should be called to cleanly terminate participation in the BEA TUXEDO application. If you look at dceserver.c, you will see that by compiling it with -DTCLIENT, code is included that calls tpinit and tpterm. The code that sets up the TPINIT buffer must be modified appropriately for your application. To provide more information with respect to administration, it might be helpful to indicate that the client is a DCE client in either the user or client name (the example sets the client name to DCECLIENT). This information shows up when printing client information from the administration interface.

Second, since the BEA TUXEDO system software is not thread-safe, the threading level passed to rpc_server_listen must be set to one. In the sample dceserver.c, the threading level is set to 1 if compiled with -DTCLIENT and to the default, rpc_c_listen_max_calls_default, otherwise.

In this configuration, the requester is built as a normal DCE client or server. Similarly, the server is built as a normal BEA TUXEDO server. The additional step is to build the gateway process, which acts as a BEA TUXEDO client using a TxRPC client stub, and a DCE server, using a DCE/RPC server stub.

The process of running the two IDL compilers and linking the resultant files is simplified with the use of the bldc_dce(1) command which builds a BEA TUXEDO client with DCE linked in.

The usage for bldc_dce is as follows.

bldc_dce [-o output_file] [-w] [-i idl_options] [-f firstfiles] \
[-l lastfiles] [idl_file . . . ]

The command takes as input one or more IDL files so that the gateway can handle one or more interfaces. For each one of these files, tidl is run to generate a client stub and idl is run to generate a server stub.

This command knows about various DCE environments and provides the necessary compilation flags and DCE libraries. If you are developing in a new environment, it may be necessary to modify the command to add the options and libraries for your environment. The source is compiled in such a way (with -DTMDCEGW defined) that memory allocation is always done using rpc_ss_allocate(3c) and rpc_ss_free(3c) to ensure that memory is freed on return. The use of -DTMDCEGW also includes DCE header files instead of BEA TUXEDO TxRPC header files.

The IDL output object files are compiled, optionally with specified application files (using the -f and -l options), to generate a BEA TUXEDO client using buildclient(1). Note that one of the files included should be the equivalent of the dceserver.o, compiled with the -DTCLIENT option.

The name of the executable client can be specified with the -o option.

When running this configuration, the BEA TUXEDO configuration must be booted before starting the DCE server so that it can join the BEA TUXEDO application before listening for DCE requests.

BEA TUXEDO Requester to DCE Service Using DCE-only

Figure 4-3 BEA TUXEDO Requester to DCE Service Using DCE-only

The approach assumes that the DCE environment is directly available to the client (this can be a restriction or disadvantage in some configurations). The client program has direct control over the DCE binding and authentication. Note that this is presumably a mixed environment in which the requester is either a BEA TUXEDO service that calls DCE services, or a BEA TUXEDO client (or server) that calls both BEA TUXEDO and DCE services.

When compiling BEA TUXEDO TxRPC code that will be used mixed with DCE code, the code must be compiled such that DCE header files are used instead of the TxRPC header files. This is done by defining -DTMDCE at compilation time, both for client and server stub files and for your application code. If you are generating object files from tidl, you must add the -cc_opt -DTMDCE option to the command line. The alternative is to generate c_source from the IDL compiler and pass this C source (not object files) to bldc_dce or blds_dce as in the following examples.

tidl -keep c_source -server none t.idl
idl -keep c_source -server none dce.idl
bldc_dce -o output_file -f client.c -f t_cstub.c -f dce_cstub.c

or

blds_dce -o output_file -s service -f server.c -f t_cstub.c -f dce_cstub.c

In this example, we are not building a gateway process so .idl files cannot be specified to the build commands. Also note that the blds_dce command cannot figure out the service name associated with the server so it must be supplied on the command line using the -s option.

DCE Requester to BEA TUXEDO Service Using BEA TUXEDO-only

Figure 4-4 DCE Requester to BEA TUXEDO Service Using BEA TUXEDO-only

In this final case, the DCE requester calls the BEA TUXEDO client stub directly.

Again, -DTMDCE must be used at compilation time, both for client and server stub files and for your application code. In this case the requester must be a BEA TUXEDO client.

tidl -keep c_source -client none t.idl
bldc_dce -o output_file -f -DTCLIENT -f dceserver.c -f t_cstub.c

Note that dceserver.c should call tpinit(3c) to join the application and tpterm(3c) to leave the application, as was discussed earlier.

Building Mixed DCE/RPC and BEA TUXEDO TxRPC Clients and Servers

This section summarizes the rules to follow if you are compiling a mixed client or server without using the bldc_dce or blds_dce commands:



[Top] [Prev] [Next] [Bottom]