Chapter 6. Receiving Messages

This chapter describes how to retrieve messages delivered to your application and how to handle the message once you have examined it. It also shows you how to send replies to requests that you receive.

To retrieve and handle ToolTalk messages, your application must perform several operations: it must be able to retrieve ToolTalk messages; it must be able to examine messages; it must be able to invoke callback routines; it must be able to respond to requests; and it must be able to destroy the message when it is no longer needed.

Retrieving Messages

When a message arrives for your process, the ToolTalk-supplied file descriptor becomes active. When notified of the active state of the file descriptor, your process must call tt_message_receive() to get a handle for the incoming message.


Note: Handles for messages remain constant. For example, when a process sends a message, both the message and any replies to the message have the same handle.

The following code sample from ttsample1_sgi illustrates how to receive a message.

/*
 * When a ToolTalk message is available, receive it; if it's
 * a ttsample1_value message, update the gauge with the new
 * value.
 */
void receive_tt_message()
{
   Tt_message msg_in;
   int mark;
   int val_in;

   msg_in = tt_message_receive();

   /* It's possible that the file descriptor would become
    * active even though ToolTalk doesn't really have a
    * message for us. The returned message handle is NULL in
    * this case.
    */

if (msg_in == NULL) return;

Identifying and Processing Messages Easily

To easily identify and process messages you receive:

  • Add a callback to a dynamic pattern with tt_pattern_callback_add(). When you retrieve the message, the ToolTalk service will invoke any message or pattern callbacks. See Chapter 3, “Dynamic Message Patterns,” for more information on placing callbacks on patterns.

  • Retrieve the message's opnum if you are receiving messages that match your ptype message patterns.

Recognizing and Handling Replies Easily

To easily recognize and handle replies to messages sent by you:

  • Place specific callbacks on requests before you send them with tt_message_callback_add(). See Chapter 5, “Sending Messages,” for more information on placing callbacks on messages.

  • Compare the handle of the message you sent with the message you just received. The handles will be the same if the message is a reply.

  • Place information meaningful to your application on the request with the tt_message_user_set() call.

Examining Messages

When your process receives a message, you examine the message and take appropriate action.

Before you start to retrieve values, obtain a mark on the ToolTalk API stack so that you can release the information the ToolTalk service returns to you all at once. The following sample code from ttsample1_sgi allocates storage, examines a message's contents, and releases the storage.

/*
 * Get a storage mark so we can easily free all the data
 * ToolTalk returns to us.
 */

mark = tt_mark();

op = tt_message_op(msg_in);
err = tt_ptr_error(op);
if (err > TT_WRN_LAST) {
   printf( "tt_message_op(): %s\n", tt_status_message(err));
} else if (op != 0) {
   if (0==strcmp("ttsample1_value", tt_message_op(msg_in))) {
      tt_message_arg_ival(msg_in, 0, &val_in);
      XtVaSetValues(gauge, XmNvalue, val_in, NULL);
   }
}

tt_message_destroy(msg_in);
tt_release(mark);
return;

Table 6-1 lists the ToolTalk functions you use to examine the attributes of a message you have received.

Table 6-1. Function to Examine Message Attributes

Return Type

ToolTalk Function

Tt_address

tt_message_address(Tt_message m)

Tt_staus

tt_message_arg_bval(Tt_message m, intn, usigned char **value, int *len)

Tt_status

tt_message_arg_ival(Tt_message m, int n,
int *value)

Tt_mode

tt_message_arg_mode(Tt_message m, int n)

char *

tt_message_arg_type(Tt_message m, int n)

char *

tt_message_arg_val(Tt_message m, int n)

int

tt_message_args_count(Tt_message m)

Tt_class

tt_message_class(Tt_message m)

Tt_disposition

tt_message_disposition(Tt_message m)

char *

tt_message_file(Tt_message m)

gid_t

tt_message_gid(Tt_message m)

char *

tt_message_handler(Tt_message m)

char *

tt_message_handler_ptype(Tt_message m)

char *

tt_message_object(Tt_message m)

char *

tt_message_op(Tt_message m)

int

tt_message_opnum(Tt_message m)

char *

tt_message_otype(Tt_message m)

Tt_pattern

tt_message_pattern(Tt_message m)

Tt_scope

tt_message_scope(Tt_message m)

char *

tt_message_sender(Tt_message m)

char *

tt_message_sender_ptype(Tt_message m)

char *

tt_message_session(Tt_message m)

Tt_state

tt_message_state(Tt_message m)

int

tt_message_status(Tt_message m)

char *

tt_message_status_string(Tt_message m)

uid_t

tt_message_uid(Tt_message m)

void *

tt_message_user(Tt_message m, int key)


Invoking Callback Routines

Figure 6-1 illustrates how the ToolTalk service invokes message and pattern callbacks when tt_message_receive() is called to retrieve a new message.

Figure 6-1. How Callbacks Are Invoked

Figure 6-1 How Callbacks Are Invoked

Handling Requests

When your process receives a request (class = TT_REQUEST), you must either reply to the request, or reject or fail the request.

Replying to Requests

When you reply to a request, you need to:

  1. Perform the requested operation.

  2. Fill in any argument values with modes of TT_OUT or TT_INOUT.

  3. Send the reply to the message.

Table 6-2 lists the ToolTalk functions you use to reply to requests.

Table 6-2. Functions to Reply to Requests

Return Type

ToolTalk Function

Tt_mode

tt_message_arg_mode(Tt_message m, int n)

Tt_status

tt_message_agr_bval_set(Tt_me ssage m, intn, const unsigned char *value, int len)

Tt_status

tt_message_arg_ival_set(Tt_message m, int n,
int value)

Tt_status

tt_message_arg_val_set(Tt_message m, int n,
const char *value)

Tt_status

tt_message_reply(Tt_message m)


Rejecting or Failing a Request

If you have examined the request and your application is not currently able to handle the request, you can use the ToolTalk functions listed in Table 6-3 to reject or fail a request.

Table 6-3. Rejecting or Failing Requests

Return Type

ToolTalk Function

Tt_status

tt_message_reject(Tt_message m)

Tt_status

tt_message_fail(Tt_message m)

Tt_status

tt_message_status_set(Tt_message m, int status)

Tt_status

tt_message_status_string_set(Tt_message m,
const char *status_str)


Rejecting a Request

If you have examined the request and your application is not currently able to perform the operation but another application might be able to do so, use tt_message_reject() to reject the request.

When you reject a request, the ToolTalk service attempts to find another receiver to handle it. If the ToolTalk service cannot find a handler that is currently running, it examines the disposition attribute, and either queues the message or attempts to start applications with ptypes that contain the appropriate message pattern.

Failing a Request

If you have examined the request and the requested operation cannot be performed by you or any other process with the same ptype as yours, use tt_message_fail() to inform the ToolTalk service that the operation cannot be performed. The ToolTalk service will inform the sender that the request failed.

To inform the sender of the reason the request failed, use tt_message_status_set() or tt_message_status_string_set() before you call tt_message_fail().


Note: The status code you specify with tt_message_status_set() must be greater than TT_ERR_LAST.


Destroying Messages

After you have processed a message and no longer need the information in the message, use tt_message_destroy() to delete the message and free storage space.