User Code Interface, Client Side



next up previous
Next: Stub InternalsServer Up: MSRPC2 User Manual Previous: User Code Interface

User Code Interface, Client Side

Creation of bindings

A client of an MSRPC2 interface binds to the interface by means of a call like:

bool_t Aubergine_Client_Bind ( 
        Aubergine_Binding  **b,
        MSRPCInterfaceRef  *ref,
        PFC          allocFunc,
        PFV          freeFunc,
        excpt_t     *exc)
The function returns TRUE if it succeeds. The parameters are:

Destruction of bindings

As on the server side, a binding can be destroyed by calling its destroy method. Again, as bindings are single-threaded, there should not be an invocation in progress over the binding. The binding pointer will be invalid after the call.

Invocations

To invoke an operation on a binding, simply call the relevant member of the ops structure of the binding. The parameters of this method are:

This will return a boolean; TRUE indicates that in some way the operation went OK and it's fine to carry on. FALSE means that something went wrong, and exceptions results have been returned. (see below).

Note that MIDDL MUTABLE parameters are not supported by MSRPC2 (at present).

Exceptions

A TRY-ENDTRY set of macros has been implemented to aid exception handing. For efficiency, these are not implemented using setjmp and longjmp, but instead use gotos. The disadvantage is a slight clouding of syntax. The exception mechanism does not pretend to be general purpose, and in particular no notion of stack unwinding is provided.

The syntax of the TRY block is as follows:

 TRY(<label>,<binding>,<operation>)
 {
   CATCH(<exceptionname>)
       <handling code>
   ...
 } ENDTRY;

label is a user provided label name that is used to allow retries. All exceptions must be caught, but maybe ignored by using the macro SUCCEED(<label) from within the handling code. It is a fatal run time error to fail to catch an exception. The statement CATCHALL may be used as the last catch statement, and matches all exceptions not mentioned in a catch block. There is no restriction on the style of C programming using within the handling code, but control must not drop through to the next CATCH statement. (In particular `break', `continue' and `return' can all be used and will apply to the enclosing structures). The following macros are provided for use within the handling code.

FAIL(<label>)
Raise the generic pseudo-exception Failure, which must be handled within the same TRY block. This is intended as a generic fail point for use by library handler routines.
RETRY(<label>)
Try the RPC again. This is equivalent to a jump to the line containing the TRY statement, so arguments to the RPC will be re-evaluated.
SUCCEED(<label>)
Jump to beyond the ENDTRY.
HANDLER(<label>,procedure call)
This calls the named procedure, and allows it to perform RETRY, FAIL or SUCCEED calls (or just return). Due to the limitations of C macros, it must use the commands hRETRY, hFAIL, hSUCCEED and hRETURN respectively (with no arguments). The procedure implementing the handler should be declared to return and integer.

In addition to these macros, the macro RETRIES(<binding>) may be used within a TRY block, and returns the number of retries (so far) on the operation that raised the exception. Within the handling code, the arguments to the exception are available via the excs structure of the binding. If variable length, it is the handlers responsibility to free any memory allocated for them. See the section on memory below.

As pthreads also provides an exception mechanism (which is unsuitable for use by MSRPC2), the macros TRY, CATCH etc are already defined for use by pthreads. Client code can either precede each of the macros by msrpc2_, #define the macro USE_MSRPC2_EXCEPTIONS before including msrpc2.h. In the latter case, pthreads own exception mechanism cannot be used.

An example TRY block is as follows;

TRY(mylab,b,Read(b,fid,offset,len,&data))
{
  CATCH(InternalError)
    printf("Internal Error status=%d\n",b->excs.u.InternalError.status);
    FAIL(mylab);
  CATCH(ReadBeyondEnd)
    len=b->excs.u.ReadBeyondEnd.actual_len;
    SUCCEED(mylab);
  CATCH(Access)
    HANDLER(mylab,handle_accessexpt(b->excs.u.Access.reason));
  CATCH(Failure)
     exit(1);
} ENDTRY;

Control parameters

As on the server side, the control method allows protocol-specific parameters of a binding such as timeouts, etc. to be set. This method must not be invoked concurrently with any invocation over the binding. op is an operation code whose meaning depends on the type of protocol the interface is using and is determined by the runtime system. param is a generic parameter whose meaning is determined by op.

Local-case optimisations

In the remote case, the ops methods of the binding object point to stub routines which marshal the arguments, send the data, receive the reply, unmarshal the results, and optionally raise exceptions in response to the reply received or local ``engineering failures''. In the local case, the methods point to the real server routines. Only one indirection is required to call a server routine.

In fact, in the local case there is only one binding object, shared by client and server. The session field is null (the run-time library is never used for local bindings).

Client binding is done by directly calling the bind method of the interface structure (see below). The address of this structure in memory is obtained from the address hint in the InterfaceRef. bind is called with a null session argument to indicate a local binding. The server binding constructor builds the binding and the client bind routine then fills in the exception routines as normal. Thus raising exceptions also optimises down to a single function call.

Control methods on a local binding always return FALSE.

Memory

If an RPC call returns variable length results (or exceptions) then the returned memory `belongs' to the caller, and it is his responsibility to free it once it is no longer required. Help is provided in the form of msdr macros to free types declared in the idl file. These required a pointer to a mm structure which contains details of the relevant memory freeing and allocating functions. A copy of the mm structure is stored in the binding for the clients use. This is also available for server code.

For example

 f_msdr_MSRPC2String(& b->mm,barman);



next up previous
Next: Stub InternalsServer Up: MSRPC2 User Manual Previous: User Code Interface



Simon Crosby and Richard Hayton