next up previous contents
Next: KADM5 self-reference Up: API Versioning Previous: Client library functions   Contents

Admin server stubs

When an RPC call arrives at the server, the RPC layer authenticates the call using the GSS-API, decodes the arguments into their single-structure form (ie: a gprinc_arg) and dispatches the call to a stub function in the server (in server_stubs.c). The stub function first checks the caller's authorization to invoke the function and, if authorized, calls the kadm5 function corresponding to the RPC function with the arguments specified in the single-structure argument.

Once again, kadm5_get_principal is a good example for the issues involved. The contents of the gprinc_arg given to the stub (get_principal_1) depends on the API version the caller on the client side specified; that version is available to the server in the api_version field of the gprinc_arg. When the server calls kadm5_get_principal in the server library, it must give that function an API handle that contains the API version requested by the client; otherwise the function semantics might not be correct. One possibility would be for the server to call kadm5_init for each client request, specifing the client's API version number and thus generating an API handle with the correct version, but that would be prohibitively inefficient. Instead, the server dips down in the server library's internal abstraction barrier, using the function new_server_handle to cons up a server handle based on the server's own global_server_handle but using the API version specified by the client. The server then passes the newly generated handle to kadm5_get_principal, ensuring the right behavior, and creates the gprinc_ret structure in a manner similar to that described above.

Although new_server_handle solves the problem of providing the server with an API handle containing the right API version number, it does not solve another problem: that a single source file, server_stubs.c, needs to be able to invoke functions with arguments appropriate for multiple API versions. If the client specifies VERSION_1, for example, the server must invoke kadm5_get_principal with three arguments, but if the client specifies VERSION_2 the server must invoke kadm5_get_principal with four arguments. The compiler will not allow this inconsistency. The server defines wrapper functions in a separate source file that match the old version, and the separate source file is compiled with USE_KADM5_API_VERSION set to the old version; see kadm5_get_principal_v1 in server_glue_v1.c. The server then calls the correct variant of kadm5_get_principal_* based on the API version and puts the return values into the gprinc_ret in a manner similar to that described above.

Neither of these solutions are necessarily correct. new_server_handle violates the server library's abstraction barrier and is at best a kludge; the server library should probably export a function to provide this behavior without violating the abstraction; alternatively, the librar should be modified so that having the server call kadm5_init for each client RPC request would not be too inefficient. The glue functions in server_glue_v1.c really are not necessary, because the server stubs could always just pass dummy arguments for the extra arguments; after all, the glue functions pass nothing for the extra arguments, so they just end up as stack garbage anyway.

Another alternative to the new_server_handle problem is to have the server always invoke server library functions at a single API version, and then have the stubs take care of converting the function arguments and results back into the form expected by the caller. In general, however, this might require the stubs to duplicate substantial logic already present in the server library and further violate the server library's abstraction barrier.


next up previous contents
Next: KADM5 self-reference Up: API Versioning Previous: Client library functions   Contents
Autobuild 2009-09-05