ToolTalk ユーザーズガイド

第 11 章 メッセージの受信

この章では、ユーザーのアプリケーションに配信されたメッセージの検索方法と検査済みメッセージの処理方法について説明します。さらに、受信した要求に対して応答を送信する方法についても説明します。

ToolTalk メッセージの検索と処理を行うには、ユーザーのアプリケーションはさまざまな操作を実行しなければなりません。ToolTalk メッセージの検索、メッセージの検査、コールバックルーチンの提供、要求への応答、および不要になったメッセージの削除を実行できる必要があります。

メッセージの検索

メッセージがユーザーのプロセスに届くと、ToolTalk が提供したファイル記述子が使用可能になります。このファイル記述子が使用可能だと通知されると、プロセスは tt_message_receive を呼び出し、着信メッセージのハンドルを取得しなければなりません。

メッセージの受信方法を例 11-1 に示します。


例 11-1 メッセージの受信

/*
 * 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;


メッセージのハンドルは不変です。たとえば、プロセスがメッセージを送信するとき、メッセージとそのメッセージに対する応答は、送信されたメッセージと同じハンドルを持ちます。例 11-2 に、TT_HANDLED のメッセージ状態を検査する方法の例を示します。


例 11-2 メッセージ状態のコード検査

Tt_message m, n;
m = tt_message_create();
...
tt_message_send(m);

... wait around for tt_fd to become active

n = tt_message_receive();
if (m == n) {
	/* This is the reply to the message we sent */
	if (TT_HANDLED == tt_message_state(m) ) {
			/* The receiver has handled the message so we can go
on */
			...
	}
} else {
	/* This is a new message coming in */
)


メッセージの容易な識別方法と処理方法

ユーザーが受信したメッセージを容易に識別および処理するには、次のようにします。

応答の容易な認識方法と処理方法

ユーザーが送信したメッセージに対する応答を容易に認識および処理するには、次のようにします。

メッセージ状態の検査

メッセージを受信したら、その状態を検査しなければなりません。メッセージ状態が TT_WRN_START_MESSAGE の場合は、応答、拒否、異常終了、tt_message_accept 呼び出しのいずれかの処理を実行しなければなりません。tt_message_accept 以外は、メッセージが通知であっても行います。

ToolTalk サービスを使って起動したプログラムで TT_WRN_START_MESSAGE の状態を受信したプログラムは、tt_message_uidtt_message_gid を確認してください。UNIX UID と GID のいずれか一方、あるいはその両方が要求と合わない場合は、TT_DESKTOP_EACCES で要求が失敗することがあります。同様に、UID や GID に不一致がある場合は、すでに実行済みのアプリケーションでは、TT_DESKTOP_EACCES で要求を拒絶することがあります。このため、マッチング ID ハンドラが見つかるか、自動起動ハンドラが要求を拒絶するまで、メッセージは連続して拒絶されます。

メッセージの検査

ユーザープロセスがメッセージを受信する場合、ユーザーはメッセージを検査して適切な処置を行います。

値の検索を開始する前に ToolTalk API スタック上のマークを取得し、ToolTalk サービスがユーザーに同時に返す情報を解放できるようにします。例 11-3 では、記憶領域を割り当て、メッセージの内容を検査し、記憶領域を解放します。


例 11-3 記憶領域の割り当て、検査、および解放

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

        mark = tt_mark();

        if (0==strcmp("ttsample1_value", tt_message_op(msg_in))) {
                tt_message_arg_ival(msg_in, 0, &val_in);
                xv_set(gauge, PANEL_VALUE, val_in, NULL);
        }

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


表 11-1 に、受信したメッセージの属性を検査するためにユーザーが使用する ToolTalk 関数を示します。

表 11-1 メッセージ属性を検査する関数

返される型 

ToolTalk 関数 

説明 

Tt_address

tt_message_address(Tt_message m)

メッセージのアドレス 

Tt_status

tt_message_arg_bval(Tt_message m, int n, unsigned char **value, int *len)

バイト配列としての引数値 

Tt_status

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

整数としての引数値 

Tt_status

tt_message_arg_xval(Tt_message m, int n, xdrproc_t xdr_proc, void *value)

xdr としての引数値 

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)

メッセージの型 (通知または要求) 

int

tt_message_contexts_count(Tt_message m);

コンテキストの数 

char *

tt_message_context_slotname(Tt_message m, int n);

メッセージの「n 番目」のコンテキスト名 

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)

ハンドラの procid 

char *

tt_message_handler_ptype(Tt_message m)

ハンドラの ptype 

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)

メッセージの受信側 (FILE、SESSION、BOTH) 

char *

tt_message_sender(Tt_message m)

送信側アプリケーションの procid 

char *

tt_message_sender_ptype(Tt_message m)

送信側アプリケーションの ptype 

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)

アプリケーション内部の隠されたデータ 

コールバックルーチン

パターンが一致してメッセージが到着した際、ToolTalk サービスにコールバックを起動するよう指示できます。

p = tt_pattern_create();
   tt_pattern_op_add(p, "EDIT");
   ... other pattern attributes
   tt_pattern_callback_add(p, do_edit_message);
   tt_pattern_register(p);


注 -

コールバックは、登録したときと逆の順序で呼び出されます (つまり、最後に追加したコールバックが最初に呼び出されます)。


新しいメッセージを検索するために tt_message_receive を呼び出した場合、ToolTalk サービスがメッセージとパターンコールバックをどのように起動するかを図 11-1に示します。

図 11-1 コールバックの起動方法

Graphic

ハンドラにアドレス指定されたメッセージのコールバック

ToolTalk サービスは、ハンドラにアドレス指定されたメッセージの受信側を判別後、その受信側が登録したすべてのパターンに対してそのメッセージを照合します。(明示的にハンドラにアドレス指定されたメッセージは「ポイントツーポイント」のメッセージであるため、パターンの照合は行いません。)

静的パターンへのコールバックの付加

静的パターンを作成する際、数値タグ (opnum) を ptype の各シグニチャに付加できます。今回のバージョンでは、opnum にコールバックを付加できます。opnum を持つ静的パターンに一致したためにメッセージが配信されると、ToolTalk サービスはその opnum に付加されたコールバックをすべて調べ、ある場合は起動します。

要求の処理

ユーザーのプロセスが要求 (class=TT_REQUEST) を受信した場合、ユーザーは要求に応答するか、要求を拒否するか、または要求を異常終了するかのどれかを選択しなければなりません。

要求への応答

要求に応答する場合は次の操作が必要です。

  1. 要求された操作を実行します。

  2. 任意の引数に TT_OUT または TT_INOUT のモードを埋め込みます。

  3. メッセージに対して応答を送信します。

    表 11-2 に、要求への応答時に使用する ToolTalk 関数を示します。

    表 11-2 要求に応答するための関数

    ToolTalk 関数 

    説明 

    tt_message_arg_mode(Tt_message m, int n)

    引数のモード (入力、出力、入出力)。返される型は Tt_mode

    tt_message_arg_bval_set(Tt_message m, int n, 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_arg_xval_set(Tt_message m, int n, xdrproc_t xdr_proc, void *value)

    返される型は Tt_status

    tt_message_context_set(Tt_message m, const char *slotname, const char *value);

    指定された文字列にコンテキストを設定する。返される型は Tt_status

    tt_message_bcontext_set(Tt_message m, const char *slotname, unsigned char *value, int length);

    指定されたバイト配列にコンテキストを設定する。返される型は Tt_status

    tt_message_icontext_set(Tt_message m, const char *slotname, int value);

    指定された整数にコンテキストを設定する。返される型は Tt_status

    tt_message_xcontext_set(Tt_message m, const char *slotname, xdrproc_t xdr_proc, void *value)

    返される型は Tt_status

    tt_message_reply(Tt_message m)

    メッセージに応答する。返される型は Tt_status

要求の拒否または異常終了

要求の検査後、ユーザーのアプリケーションが現在その要求を処理できない場合は、表 11-3 に一覧表示された ToolTalk 関数を使って、要求を拒否または異常終了できます。

表 11-3 要求の拒否または異常終了

ToolTalk 関数 

説明 

tt_message_reject(Tt_message m)

メッセージを拒否する 

tt_message_fail(Tt_message m)

メッセージを異常終了する 

tt_message_status_set(Tt_message m, int status)

メッセージの状態を設定する。受信側アプリケーションは、この状態を見ることができる 

tt_message_status_string_set(Tt_message m, const char *status_str)

メッセージの状態を記述するテキストを設定する。受信側アプリケーションは、このテキストを見ることができる 

これらの要求の返される型は Tt_status です。

要求の拒否

要求の検査後、ユーザーのアプリケーションが現在その要求を処理できないが別のアプリケーションを使えば処理できる場合は、tt_message_reject を使ってその要求を拒否します。

ユーザーが要求を拒否すると、ToolTalk サービスはその要求を処理するための別の受信側を見つけようとします。ToolTalk サービスは、現在実行中のハンドラを発見できない場合、処置属性を検査し、メッセージを待ち行列に入れるか、適切なメッセージパターンが入った ptype でアプリケーションを起動しようとします。

要求の異常終了

要求の検査後、ユーザーまたはユーザーと同じ ptype の他のプロセスが要求された操作を実行できない場合は、tt_message_fail を使って、その操作が実行できないことを ToolTalk サービスに知らせます。ToolTalk サービスは、要求が異常終了したことを送信側に知らせます。

送信側に要求が異常終了した理由を知らせるには、tt_message_fail を呼び出す前に、tt_message_status_set または tt_message_status_string_set を使用します。


注 -

tt_message_status_set によってユーザーが指定した状態コードは、TT_ERR_LAST より大きくなければなりません。


オファの監視

使用プロセスで TT_SENT 状態のオファ (class=TT_OFFER) を受信したときは、次のいずれか 1 つを実行する必要があります。

  1. メッセージの tt_message_accept ( ) を呼び出してオファを受信します。これにより、送信側の procid に対して受信側の procid がオファを受信したことを知らせます。

  2. メッセージの tt_message_reject ( ) を呼び出してオファを拒絶します。これにより、送信側の procid に対して受信側の procid がオファを拒絶したことを知らせます。

  3. メッセージの tt_message_destroy ( ) を呼び出して、オファを最初に受け入れたり拒絶したりせずに忌避します。これにより、送信側の procid に対して、受信側の procid がオファを忌避したことを知らせます。

  4. メッセージの tt_message_receive ( ) をもう一度呼び出して、オファを最初に受け入れたり拒絶したりせずに忌避します。この場合も、送信側の procid に対して受信側の procid がオファを忌避したことを知らせます。

  5. tt_close ( ) を呼び出すか、(正常終了あるいは異常終了で) 終了させることによって ToolTalk サービスを切断します。この場合、クライアントプロセスが接続されている ttsession プロセスは、そのクライアントプロセスをオファから忌避していると見なします。

ハンドラがある場合は、ハンドラと監視者のすべてがメッセージを受け入れるか、拒絶または忌避した場合は、メッセージ状態 (Tt_state) は TT_RETURNED に設定されます。他のメッセージクラスにないオファの中間状態は、次のように定義されます。

  1. TT_ACCEPTED - 受信側がオファに対して tt_message_accept ( ) を実行すると、オファはこの状態になります。

  2. TT_REJECTED - 受信側がオファに対して tt_message_reject ( ) を実行すると、オファはこの状態になります。

  3. TT_ABSTAINED - 受信側が上記の 3、4、5 のいずれかを選択すると、オファはこの状態になります。

メッセージの削除

メッセージの処理が完了し、メッセージの情報が必要なくなった場合は、tt_message_destroy を使ってメッセージを削除し、記憶領域の容量を解放します。