The IDL compiler generates some additional member functions for an interface class. For clients, these functions include overloaded static member functions to bind to remote named objects in various ways and a member function to set security information. For servers, additional member functions exist to advertise named objects and get the binding handle on which a member function was called from within the member function implementation.
Four overloaded functions for binding clients to known objects are named bind( ). The functions otherwise differ by the type of parameter passed in. Three of these functions are intended for use with named objects and one is used to swap between interfaces when an object supports more than one interface. Each bind( ) function obtains an object reference (instead of a proxy class) by returning a pointer to the interface class. These functions are described in the following paragraphs.
The bind( ) Function for Binding by an Object's Name
A client can bind to a named object (an object whose name is advertised in a name service) by calling the
idl-generated bind( ) static member function with the name service name as an argument. The function's prototype is as follows:
interface_class *
interface_class::bind(unsigned_char_t *)
This function takes a pointer argument of type unsigned_char_t that points to a name service name. The function returns a pointer to the interface class. For example:
char *CDS_name = "/.;/object_name";
IF_class * object = IF_Class::bind( (unsigned_char_t *) CDS_name);
If the entry contains more than one binding, one is returned at random. The function obtains a full binding (the binding information includes a server's endpoint.)
Before a client uses this function, a persistent object on a server typically places its name and binding information in the name service by using the idl-generated register_named_object( ) member function.
The bind( ) Function for Binding by an Object's UUID
A client can bind to a named object by using the object's UUID as an argument to the idl-generated bind( ) static
member function. This function's prototype is as follows:
interface_class * interface_class::bind( uuid_t &)
This function takes an argument of type uuid_t that is the UUID of a named object. The function returns a pointer to the interface class: For example:
uuid_t objectUUID;
interface_class * object = interface_class::bind(objectUUID);
The search in the namespace for an entry that contains the matching UUID begins with the default entry named in the RPC_DEFAULT_ENTRY environment variable. The binding obtained is fully bound.
The bind( ) Function for Binding by Binding Handle
A client can bind to a known object directly by using a binding handle as an argument to the idl-generated
bind( ) static member function. The function's prototype is as follows:
interface_class * interface_class::bind( rpc_binding_handle_t)
This function takes an argument of type rpc_binding_handle_t that is a binding handle to an object. The function returns a pointer to the interface class. For example:
rpc_binding_handle_t bindingHandle;
interface_class * object - interface_class::bind(bindingHandle);
This function does note use the name service because the client obtains the binding information and binding handle prior to the call. The binding handle can be either partially or fully bound. If the binding handle is partially bound, it becomes fully bound when the object calls a member function.
The bind( ) Function for Binding by Object Reference
Depending on the application, objects can have the behavior of more than one interface class. However, your code can access
only one interface's member function at a time. A client uses the idl-generated bind( ) static member function with an existing object reference as an argument to bind to a
different interface. This function's prototype is as follows:
different_interface_class * different_interface_class::bind( rpc_object_reference *)
This function takes a pointer argument of type rpc_object_reference that is an existing object reference to an interface class. The function returns a pointer to a different interface class that the object also supports. The original object is obtained through a previous bind( ) call, an object creator function, or an output parameter of a member function. For example:
rpc_binding_handle_T bindingHandle;
interface_class * object = interface_class::bind(bindingHandle);
diff_if_class * new_object = diff_if_class::bind(object);
The secure( ) Function for Setting Object Security
Objects use the idl-generated secure( ) member function to set their authorization and authentication
information from the client. This sets the information for all the binding handles encapsulated in the client proxy object. The secure( ) function is a public member function of the
rpc_object_reference class. This function's prototype is as follows:
void interface_class::secure(
[unsigned_char_t * server_principal_name =0,]
[unsigned32 protection_level =rpc_c_protect_level_default,]
[unsigned32 authentication_protocol =rpc_c_authn_default,]
[rpc_auth_identity_handle_t authorization_identity =NULL,]
[unsigned32 authorization_policy =rpc_c_authz_name]
)
The following code shows an example of how to use the secure( ) function:
Matrix *m;
cout << "creating a remote matrix" << endl;
m = Matrix::createMatrix(1, 2, 3, 4);
cout << "calling set()
operation without authorization" << endl;
m->set(0,0,99);
// Without authorization, operation should have not changed anything.
assert(m->get(0,0) == 1);
cout << "setting security privileges on object" << endl;
m->secure(
(unsigned_char_t *) "refmon_test", // server principal name
rpc_c_protect_level_pkt_integ, // protection level
rpc_c_authn_dce_secret, // authentication protocol
NULL,
// inherited login context
rpc_c_authz_name // authorization policy
);
// since we now have set security
flags, the set() operation should work
m->set(0,0,99);
assert(m->get(0,0) == 99);
The example shows that unauthorized use of a matrix's member function will not change values (m->get(0,0,99);). However, after setting the appropriate authorization and authentication information with secure( ), the member function will work as expected. All parameters to the secure( ) function are optional, but it is recommended that you specify values rather that depend on the default values.
The SetRebind( ) Function
A client can automatically rebind to an object if the client first sets a rebind policy by using the SetRebind( ) function. This allows a
degree of fault tolerance in an application. For example, if a server goes down and is restarted, the client can re-establish communications with the new server. In another example, if a server
provides access over multiple protocols or addresses and one of those links fails, the client can choose another link automatically. Finally, if multiple servers support the same object and one
server exits, clients can still access the object via another server.
The format of the function is as follows:
void interface_class::SetRebind(
DCERebindPolicy policy,
[ unsigned32 *
n = 0 ]
)
The second argument is optional and only used when the rebind policy is attempt_rebind_n. The valid policies include the following:
attempt_rebind_n
If a communication fails, try to communicate with the object by selecting another binding until successful or until n attempts have been tried.
wait_on_rebind
If a communication fails, try to communicate with the object by selecting another binding until successful or until the calling thread is canceled.
attempt_rebind
If a communication fails, try to communicate with the object by selecting another binding, if possible. If all handles have been tried, return an error. This is
the default policy.
never_rebind
If a communication fails, return an error.
The register_named_object( ) Function
Persistent objects can name and register themselves from the server by using the idl-generated register_named_object( )
member function. This function performs the following tasks:
· Creates the name service entry (if it does not already exist) and adds the server's binding information so clients can find the server's host
· Replaces or adds the object's binding information in this host's endpoint map so clients can find this server
This functions prototype is as follows:
void interface_class:register_named_object(
unsigned_char_t *
name_service_name
[,boolean32 replace_endpoint = TRUE ]
)
The function takes a pointer argument of type unsigned_char_t, representing the name to use for the name service entry. The function has an optional second argument of type boolean32 to indicate whether to replace or add the object's binding information to the host's endpoint map. If the second argument is not used (or is set to TRUE) and the object's binding information already exists, this function replaces the information. If the second argument is set to FALSE, the object's binding information is added to the endpoint map (not replaced). You should add the binding information rather than replace it in circumstances where a single host has more than one server that offers the same interface. The function does not return a value.
The get_binding_handle( ) Function
Server manager code used the idl-generated get_binding_handle( ) function to obtain the binding handle used to invoke the
call. The function's prototype is as follows:
rpc_binding_handle_t get_binding_handle( );
Member functions (that are not static) cannot have an explicit binding handle argument because the handle is encapsulated in the rpc_object_reference base class. A member function implementation uses this function to obtain the binding handle to verify security information, among other things.