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 provide 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.
Example 11-1 illustrates how to receive a message.
Example 11-1 Receiving a Message
|
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 as the sent message. Example 11-2 is an example of how you can check the message state for TT_HANDLED.
Example 11-2 Code Checking the Message State
|
Identifying and Processing Messages Easily
To easily identify and process messages received by you:
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 9, 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 8, 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.
Checking Message Status
When you receive a message, you must check its status. If the status is TT_WRN_START_MESSAGE, you must either reply, reject, or fail the message even if the message is a notice, or issue a tt_message_accept call. Programs started using the ToolTalk service that receive a status of TT_WRN_START_MESSAGE should check tt_message_uid() and tt_message_gid(). You may want to fail the request with TT_DESKTOP_EACCES if the UNIX UID and/or GID do not agree with the request. Similarly, applications already running may want to reject requests with TT_DESKTOP_EACCES if there is UID or GID disagreement. This will cause serial rejection of the message until either a matching-ID handler is found, or an autostarted handler fails the request.
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. Example 11-3 allocates storage, examines message contents, and releases the storage.
Example 11-3 Allocating, Examining, and Releasing Storage
|
Table 11-1 lists the ToolTalk functions you use to examine the attributes of a message you have received.
Table 11-1 Functions to Examine Message Attributes
Return Type | ToolTalk Function | Description |
---|---|---|
Tt_address | tt_message_address(Tt_message m) | The address of the message. |
Tt_status | tt_message_arg_bval(Tt_message m, int n, unsigned char **value, int *len) | The argument value as a byte array. |
Tt_status | tt_message_arg_ival(Tt_message m, int n, int *value) | The argument value as an integer. |
Tt_status | tt_message_arg_xval(Tt_message m, int n, xdrproc_t xdr_proc, void *value) | The argument value as an xdr. |
Tt_mode | tt_message_arg_mode(Tt_message m, int n) | The argument mode (in, out, inout). |
char * | tt_message_arg_type(Tt_message m, int n) | The argument type. |
char * | tt_message_arg_val(Tt_message m, int n) | The argument value as a string. |
int | tt_message_args_count(Tt_message m) | The number of arguments. |
Tt_class | tt_message_class(Tt_message m) | The type of message (notice or request). |
int | tt_message_contexts_count(Tt_message m); | The number of contexts. |
char * | tt_message_context_slotname(Tt_message m, int n); | The name of a message's nth context. |
Tt_disposition | tt_message_disposition(Tt_message m) | How to handle the message if there is no receiving application running. |
char * | tt_message_file(Tt_message m) | The name of the file to which the message is scoped. |
gid_t | tt_message_gid(Tt_message m) | The group identifier of the sending application. |
char * | tt_message_handler(Tt_message m) | The procid of the handler. |
char * | tt_message_handler_ptype(Tt_message m) | The ptype of the handler. |
char * | tt_message_object(Tt_message m) | The object to which the message was sent. |
char * | tt_message_op(Tt_message m) | The operation name. |
int | tt_message_opnum(Tt_message m) | The operation number. |
char * | tt_message_otype(Tt_message m) | The object type to which the message was sent. |
Tt_pattern | tt_message_pattern(Tt_message m) | The pattern to which the message is to be matched. |
Tt_scope | tt_message_scope(Tt_message m) | Who is to receive the message (FILE, SESSION, BOTH). |
char * | tt_message_sender(Tt_message m) | The procid of the sending application. |
char * | tt_message_sender_ptype(Tt_message m) | The ptype of the sending application. |
char * | tt_message_session(Tt_message m) | The session from which the message was sent. |
Tt_state | tt_message_state(Tt_message m) | The current state of the message. |
int | tt_message_status(Tt_message m) | The current status of the message. |
char * | tt_message_status_string(Tt_message m) | Text describing the current status of the message. |
uid_t | tt_message_uid(Tt_message m) | The user identifier of the sending application. |
void * | tt_message_user(Tt_message m, int key) | Opaque data internal to the application. |