PreviousNext

Sample Code

The sample server application source compiles a message catalog as well as the required auxiliary .c and .h files from a sams file. In part, the file looks like the following (for the full file, see A Sample Application):

# Part I
component smp
table smp__table
technology dce

####################################################################
# Part II
serviceability table smp_svc_table handle smp_svc_handle
start
subcomponent smp_s_server "server" smp_i_svc_server
subcomponent smp_s_manager "manager" smp_i_svc_manager
subcomponent smp_s_binder "binder" smp_i_svc_binder
end

####################################################################
# Part III
# Note that defining the "sub-component" and "attributes" fields
# will result in a convenience macro's being generated for the
# message in question...

start
code sign_on
subcomponent smp_s_server
attributes "svc_c_sev_notice"
text "Starting up"
explanation ""
action "None required."
end

start
code cleanup
subcomponent smp_s_server
attributes "svc_c_sev_notice"
text "Cleaning up"
explanation "Starting server cleanup"
action "None required."
end

start
code server_exit
subcomponent smp_s_server
attributes "svc_c_sev_notice"
text "Exiting"
explanation ""
action "None required."
end

start
code signal_catcher
subcomponent smp_s_server
attributes "svc_c_sev_notice"
text "Spawning signal handler thread"
explanation ""
action "None required."
end

start
code no_signal_catcher
subcomponent smp_s_server
attributes "svc_c_sev_notice"
text "Spawn signal handler failed"
explanation "RPC runtime error. pthread_create() failed."
action ""
end

start
code bad_entryname_count
subcomponent smp_s_server
attributes "svc_c_sev_notice"
text "Bad entryname count"
explanation "Count of entrynames doesn't match count of object uuids"
action ""
end

start
code cannot_resolve_name
subcomponent smp_s_server
attributes "svc_c_sev_notice"
text "Can't resolve name"
explanation "ACL manager resolver failed to resolve name"
action "The ACL databases may be corrupt and need to be regenerated."
end

start
code cannot_manage_keys
subcomponent smp_s_server
attributes "svc_c_sev_notice"
text "Can't spawn key management thread."
explanation "RPC runtime error."
action ""
end

start
code no_acl_dbs
subcomponent smp_s_server
attributes "svc_c_sev_notice"
text "ACL databases not found, creating them from scratch"
explanation ""
action "None required."
end

start
code exporting_to
subcomponent smp_s_server
attributes "svc_c_sev_notice"
text "Exporting to %s"
explanation "Exporting to CDS entry"
action "None required."
end

start
code unexporting_from
subcomponent smp_s_server
attributes "svc_c_sev_notice"
text "Unexporting from %s"
explanation "Unexporting from CDS entry"
action "None required."
end

start
code importing_from
subcomponent smp_s_server
attributes "svc_c_sev_notice"
text "Importing from %s"
explanation "Importing from CDS entry"
action "None required."
end

start
code auth_set_client
subcomponent smp_s_server
attributes "svc_c_sev_notice"
text "Beginning client authentication setup"
explanation ""
action "None required."
end

start
code bindings_received
subcomponent smp_s_server
attributes "svc_c_sev_notice"
text "Nr of %s bindings received == %d"
explanation "Server diagnostic message."
action "None required."
end

start
code full_binding
subcomponent smp_s_server
attributes "svc_c_sev_notice"
text "Full %s binding in string form == %s"
explanation "Server diagnostic message."
action "None required."
end

start
code server_error
subcomponent smp_s_server
attributes "svc_c_sev_fatal"
text "%s: %s"
explanation "general error message"
action "?"
end

start
code no_permissions
subcomponent smp_s_manager
attributes "svc_c_sev_notice"
text "No permissions"
explanation "Client does not have permissions for operation"
action "None required."
end

start
code object_not_found
subcomponent smp_s_manager
attributes "svc_c_sev_error"
text "Object not found"
explanation "object was not found in UUID-indexed database"
action "None required."
end

start
code manager_error
subcomponent smp_s_manager
attributes "svc_c_sev_fatal"
text "%s: %s"
explanation "general error message"
action "?"
end

start
code binder_error
subcomponent smp_s_binder
attributes "svc_c_sev_fatal"
text "%s: %s"
explanation "general error message"
action "?"
end

####################################################################
# Part IIIa
# Messages for serviceability table
#
# Note that there has to be one of these for each of
# the subcomponents declared in the second part of
# the file (above)...


start !intable undocumented
code smp_i_svc_server
text "Sample server"
end

start !intable undocumented
code smp_i_svc_binder
text "Sample object binder"
end

start !intable undocumented
code smp_i_svc_manager
text "Sample manager"
end

The server main() function then establishes the required serviceability context and defines a message table with the following calls:

/* Set the program name for serviceability messages... */
dce_svc_set_progname(argv[0], &status);

/* Get serviceability handle... */
smp_svc_handle = dce_svc_register(smp_svc_table,
(idl_char*)"smp",
&status);

/* Set up in-memory serviceability message table... */
dce_msg_define_msg_table(smp__table,
sizeof smp__table / sizeof smp__table[0],
&status);

The following fragments illustrate remote error handling using a common status parameter. The .idl file for the sample interface includes the following declarations:

void sample_call(
[in] handle_t binding,
[out] long *status,
[in,out] error_status_t *remote_status);

This is matched in the .acf file by the following:

interface sample
{
sample_call([comm_status,fault_status] remote_status);
}

Then, for example, the server implementation of the sample_call( ) remote call can return the smp_s_no_perms status code on authorization failure:

void
sample_call(
rpc_binding_handle_t binding, /* Client binding. */
idl_long_int *status,
error_status_t *remote_status)
{

extern uuid_t sample_acl_mgr_uuid, sample_acl_uuid;
boolean32 authorized = 0;

/* We have to explicitly initialize the remote status value; */
/* otherwise, if no error occurs in the transmission (which */
/* would cause the runtime to assign an error value to this */
/* variable), its value will be whatever it happened to be */
/* when the RPC was made by the client... */
*remote_status = rpc_s_ok;

DCE_SVC_DEBUG((smp_svc_handle,
smp_s_manager,
svc_c_debug6,
"Entering sample_call()..."));

/* Check whether client is authorized or not... */
DCE_SVC_DEBUG((smp_svc_handle,
smp_s_manager,
svc_c_debug6,
"Calling dce_acl_is_client_authorized()..."));

dce_acl_is_client_authorized(
binding, /* Client's binding handle. */
&sample_acl_mgr_uuid, /* ACL manager type UUID. */
&sample_acl_uuid, /* The ACL UUID. */
NULL, /* Pointer to owner's UUID. */
NULL, /* Pointer to owner's group's UUID. */
sec_acl_perm_read, /* The desired privileges. */
&authorized, /* Will be TRUE or FALSE on return. */
remote_status);

if (*remote_status != error_status_ok)
{
print_manager_error("dce_acl_is_client_authorized()",
*remote_status);
return;
}

if (authorized)
{
DCE_SVC_DEBUG((smp_svc_handle,
smp_s_manager,
svc_c_debug8,
"Call authorized"));

/* HERE'S WHERE WE SHOULD ACTUALLY DO SOMETHING! */

*status = error_status_ok;
}
else
{
DCE_SVC_DEBUG((smp_svc_handle,
smp_s_manager,
svc_c_debug8,
"Call not authorized"));

/* Return no permissions status to client */
*status = no_permissions;
}

DCE_SVC_DEBUG((smp_svc_handle,
smp_s_manager,
svc_c_debug6,
"Successfully exiting sample_call()"));

}

The client making the sample_call( ) remote call can then check both RPC comm and fault status and application-specific status and display any error messages with the same code:

sample_call(binding_h, &rpc_status, &rpc_remote_status);
if (rpc_remote_status != error_status_ok)
{
print_error("sample_call()", rpc_remote_status);
exit(1);
}