The <Interface>_Client_Bind function does pretty much the obvious thing. The first thing is to check inside the interface ref to see if the interface is local.
Local bindings are created by calling the bind method on the interface itself. The address hint in the interface ref provides the address of the interface structure. If this works, the exception handlers are written in and the operation is complete.
For the remote case the binding structure is malloced. The exceptions are filled it, as are the operation stub routines, which are called C_<Operation Name>. The special methods C_Binding_Destroy and C_Binding_Control are also filled in.
Finally clnt_bind is called to create the binding.
The stub routine:
static void C_Binding_Destroy( Beer_Binding * self )is bound to the destroy method of a binding at bind time. If the binding is a true remote one (indicated by a non-null session field, it calls the destroy method of the client session block. It then frees the binding structure.
Operation methods for local clients are simply the server routines themselves. For remote sessions they are bound to internal routines, for example:
static bool_t C_LastOrders( Beer_Binding *self, MSRPCBoolean time )These stubs work by calling methods on the clntSession structure, passing the session itself along with an MSDR * for holding marshalling state and an excpt_t for signalling failures. If any session method returns false, the stub simply calls the exception dispatcher to signal an engineering failure.
The first method called is call_init to set up a packet for marshalling into. The arguments to for the call are then marshalled in.
Announcements and interrogations are handled differently since in the announcement case the run time library should not be expecting any return. Thus when marshalling has been successfully completed the stub either invokes the announce or call method to send the packet.
In the case of an interrogation the arguments are simply unmarshalled before returning.
Each client interface stub has a single exception handler:
static bool_t C_Exception_Dispatch( Beer_Binding * self, excpt_t * exc )-which is called whenever the rest of the stub detects something may have gone wrong. This includes user-defined exception conditions from the server. exc will contain the details of the exception (its procedure number, which is always 1 for engineering failures), plus a status code and error number which only have meaning for engineering failures. A simply case statement calls an internal exception stub for each exception. These have the same naming convention as operation stubs, and the same signature as the dispatcher itself. It is their responsibility to unmarshal exception arguments and set the exception name pointer in the binding.
Bad exception procedure numbers raise an InternalError exception in the dispatcher.
Note that local exceptions are not dispatched; special same domain stubs are invoked directly through the binding structure. these fill in the binding excs structure exactly like the normal stubs (except that the arguments do not need to be unmarshalled).
See the same section for the server side, above.