この章では、ユーザーのアプリケーションに配信されたメッセージの検索方法と検査済みメッセージの処理方法について説明します。さらに、受信した要求に対して応答を送信する方法についても説明します。
ToolTalk メッセージの検索と処理を行うには、ユーザーのアプリケーションはさまざまな操作を実行しなければなりません。ToolTalk メッセージの検索、メッセージの検査、コールバックルーチンの提供、要求への応答、および不要になったメッセージの削除を実行できる必要があります。
メッセージがユーザーのプロセスに届くと、ToolTalk が提供したファイル記述子が使用可能になります。このファイル記述子が使用可能だと通知されると、プロセスは tt_message_receive を呼び出し、着信メッセージのハンドルを取得しなければなりません。
メッセージの受信方法を例 11-1 に示します。
メッセージのハンドルは不変です。たとえば、プロセスがメッセージを送信するとき、メッセージとそのメッセージに対する応答は、送信されたメッセージと同じハンドルを持ちます。例 11-2 に、TT_HANDLED
のメッセージ状態を検査する方法の例を示します。
ユーザーが受信したメッセージを容易に識別および処理するには、次のようにします。
tt_pattern_callback_add を使って、コールバックを動的パターンに追加します。メッセージを検索する場合、ToolTalk サービスは任意のメッセージコールバックまたはパターンコールバックを呼び出します。コールバックをパターンに置く方法については、第 9 章「動的メッセージパターン」を参照してください。
ptype のメッセージパターンに一致するメッセージを受信している場合、メッセージの opnum を検索します。
ユーザーが送信したメッセージに対する応答を容易に認識および処理するには、次のようにします。
tt_message_callback_add を使って、送信する前に特定のコールバックを要求します。コールバックをメッセージに置く方法については、第 8 章「メッセージの送信」を参照してください。
受信したばかりのメッセージと送信したメッセージのハンドルを比較します。そのメッセージが応答の場合は、ハンドルは同じになります。
メッセージを受信したら、その状態を検査しなければなりません。メッセージ状態が TT_WRN_START_MESSAGE
の場合は、応答、拒否、異常終了、tt_message_accept 呼び出しのいずれかの処理を実行しなければなりません。tt_message_accept
以外は、メッセージが通知であっても行います。
ToolTalk サービスを使って起動したプログラムで TT_WRN_START_MESSAGE
の状態を受信したプログラムは、tt_message_uid と tt_message_gid を確認してください。UNIX UID と GID のいずれか一方、あるいはその両方が要求と合わない場合は、TT_DESKTOP_EACCES
で要求が失敗することがあります。同様に、UID
や GID に不一致がある場合は、すでに実行済みのアプリケーションでは、TT_DESKTOP_EACCES
で要求を拒絶することがあります。このため、マッチング ID ハンドラが見つかるか、自動起動ハンドラが要求を拒絶するまで、メッセージは連続して拒絶されます。
ユーザープロセスがメッセージを受信する場合、ユーザーはメッセージを検査して適切な処置を行います。
値の検索を開始する前に ToolTalk API スタック上のマークを取得し、ToolTalk サービスがユーザーに同時に返す情報を解放できるようにします。例 11-3 では、記憶領域を割り当て、メッセージの内容を検査し、記憶領域を解放します。
表 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に示します。
ToolTalk サービスは、ハンドラにアドレス指定されたメッセージの受信側を判別後、その受信側が登録したすべてのパターンに対してそのメッセージを照合します。(明示的にハンドラにアドレス指定されたメッセージは「ポイントツーポイント」のメッセージであるため、パターンの照合は行いません。)
メッセージがパターンに一致しなかった場合、そのメッセージは通常の方法で配信されます。
メッセージがパターンに一致した場合、そのパターンに付加されているコールバックがすべて起動されます。
静的パターンを作成する際、数値タグ (opnum) を ptype の各シグニチャに付加できます。今回のバージョンでは、opnum にコールバックを付加できます。opnum を持つ静的パターンに一致したためにメッセージが配信されると、ToolTalk サービスはその opnum に付加されたコールバックをすべて調べ、ある場合は起動します。
ユーザーのプロセスが要求 (class=TT_REQUEST) を受信した場合、ユーザーは要求に応答するか、要求を拒否するか、または要求を異常終了するかのどれかを選択しなければなりません。
要求に応答する場合は次の操作が必要です。
要求された操作を実行します。
任意の引数に TT_OUT または TT_INOUT のモードを埋め込みます。
メッセージに対して応答を送信します。
表 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 つを実行する必要があります。
メッセージの tt_message_accept ( ) を呼び出してオファを受信します。これにより、送信側の procid に対して受信側の procid がオファを受信したことを知らせます。
メッセージの tt_message_reject ( ) を呼び出してオファを拒絶します。これにより、送信側の procid に対して受信側の procid がオファを拒絶したことを知らせます。
メッセージの tt_message_destroy ( ) を呼び出して、オファを最初に受け入れたり拒絶したりせずに忌避します。これにより、送信側の procid に対して、受信側の procid がオファを忌避したことを知らせます。
メッセージの tt_message_receive ( ) をもう一度呼び出して、オファを最初に受け入れたり拒絶したりせずに忌避します。この場合も、送信側の procid に対して受信側の procid がオファを忌避したことを知らせます。
tt_close ( ) を呼び出すか、(正常終了あるいは異常終了で) 終了させることによって ToolTalk サービスを切断します。この場合、クライアントプロセスが接続されている ttsession プロセスは、そのクライアントプロセスをオファから忌避していると見なします。
ハンドラがある場合は、ハンドラと監視者のすべてがメッセージを受け入れるか、拒絶または忌避した場合は、メッセージ状態 (Tt_state) は TT_RETURNED
に設定されます。他のメッセージクラスにないオファの中間状態は、次のように定義されます。
TT_ACCEPTED
-
受信側がオファに対して tt_message_accept ( ) を実行すると、オファはこの状態になります。
TT_REJECTED
-
受信側がオファに対して tt_message_reject ( ) を実行すると、オファはこの状態になります。
TT_ABSTAINED
-
受信側が上記の 3、4、5 のいずれかを選択すると、オファはこの状態になります。
メッセージの処理が完了し、メッセージの情報が必要なくなった場合は、tt_message_destroy を使ってメッセージを削除し、記憶領域の容量を解放します。