原文はこちら。翻訳にあたって、オープンソースグループ・ジャパンの MIT ライセンスの訳を参考にした。
関数型(function prototype)の表記を一部変更。「〜 〜Proc(〜)」を「typedef 〜 (*Ice〜Proc)(〜)」に変更。そうしないと、別の箇所の文章や他の関数の定義と合わなくなる。明らかに関数名が間違っているところも改めた。(「IcePoAuthProc」のところが「IcePoAuthStatus」に、「IcePaAuthStatus IcePaAuthProc」とあるべきところが「IcePoAuthStatus PoAuthStatus」になっていた。)
X Version 11, Release 7.7
Version 1.0
Copyright © 1993, 1994, 1996 X Consortium
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium.
(訳)
(以下に定める条件に従い、本ソフトウェアおよび関連文書のファイル(以下「ソフトウェア」)の複製を取得するすべての人に対し、ソフ トウェアを無制限に扱うことを無償で許可する。これには、ソフトウェアの複製を使用、複写、変更、結合、掲載、頒布、サブライセンス、および/または販売 する権利、およびソフトウェアを提供する相手に同じことを許可する権利も無制限に含まれる。)
(上記の著作権表示および本許諾表示を、ソフトウェアのすべての複製または重要な部分に記載するものとする。)
(ソフトウェアは「現状のまま」で、明示であるか暗黙であるかを問わず、何らの保証もなく提供される。ここでいう保証には、商品性、特 定の目的への適合性、および権利非侵害についての保証も含まれるが、それに限定されるものではない。X CONSORTIUM は、契約行為、不法行為、またはそれ以外であろうと、ソフトウェアに起因または関連し、あるいはソフトウェアの使用またはその他の扱いによって生じる一切 の請求、損害、その他の義務について何らの責任も負わないものとする。)
(X Consortium の名称は、この表示に記載されている場合を除き、X Consortium の事前の書面による承認を得ずに、宣伝であろうとその他の形であろうと、ソフトウェアの販売を促進するもの、またはソフトウェアの使用その他の扱いを奨励 するものに使用してはならない。)
目次
クライアント間の交信に使えるプロトコルとしては、様々なものが考えられる。そして、その種のプロトコルの間には多 くの類似点と共通の機能が見出せる。例えば、認証(authentication)、版の交渉(version negotiation)、バイト順の交渉(byte order negotiation)などである。Inter-Client Exchange (ICE) プロトコルの狙いは、そのようなプロトコルを構築するための骨組みを規定することである。ICE プロトコルを用いることで、共通の交渉機構を使い回せるようになるとともに、単一の伝送接続(transport connection)上での多重プロトコル通信が可能になる。
ICE を利用しようとするクライアントは、まず自身が理解できるプロトコルの群を ICE
ライブラリに登録しなければならない。各プロトコルに対して、主たる命令コード(major opcode)が動的に割りてられる。主命令コードは 1 -
255
の範囲の値をとる(交信を試みる二つのクライアントの間で、同一のプロトコルに対して異なる主命令コードが割り当てられることもある)。次にクライアント
は他のクライアントとの接続を開くか、さもなくば、他のクライアントからの接続を待ち受ける。この段階で認証を行うことができる。一つのクライアントが、
他のクライアントへの接続を図りながら、同時に自身への接続を待ち受けるということも可能である(入れ籠型のセッションマネージャがその例)。二つのクラ
イアントの間に一度 ICE 接続が確立された後、使用したいプロトコルを「活性化」するために、クライアントの一方から ProtocolSetup
を提起する必要がある。他の一方が ProtocolSetup
を受理すると(ここでも認証を行うことができる)、両クライアントはそのプロトコル固有のメッセージ群を用いて交信できるようになる。単一の ICE
接続の上で、複数のプロトコルを稼働させることが可能である。ある ICE 接続において最早使われていないプロトコルが存在するとき、ICE
ライブラリにその旨を通知するのはクライアントの仕事である。但し、各下位プロトコル(subprotocol)がプロトコルの終了作業を開始する方法に
ついては、ICE では定めない。
ICE ライブラリでは、受け取ったメッセージを処理するためにコールバック(callback)を利用している。コールバックを用いることで、ProtocolSetup
メッセージや認証作業を舞台裏で始末できるようになる。クライアントが特定のメッセージを待ち受けて処理から返らない(block)時に、ICE ライブラリで他のメッセージのために領域を確保する必要がない、ということもコールバックの利点の一つである。
この文書は主に、ICE を基層としたプロトコルのライブラリを開発する人に向けて書かれている。一般的には、ICE を利用するアプリケーションは直接 ICE ライブラリの関数を呼び出すのではなく、個々のプロトコル・ライブラリの関数を呼び出すものである。しかしながら、ICE 接続を受け入れるため、交信開始時に ICE ライブラリの関数をいくらか呼び出さなければならないアプリケーションも存在するであろう(例えば、クライアントからの接続を受け付けるセッションマネー ジャなど)。とはいえ、総じてプロトコル・ライブラリは、 ICE 内部の細かい点をアプリケーションから隠すように設計すべきである。
ヘッダファイル <X11/ICE/ICElib.h> で ICElib の全てのデータ型と関数型(function prototype)を定義する。ICElib.h
はヘッダファイル <X11/ICE/ICE.h> を取り込んでいる(include)。ICE.h
で ICElib の全ての定数を定義する。メッセージの読み書きを行う必要のあるプロトコル・ライブラリは、ヘッダファイル <X11/ICE/ICEmsg.h> を取り込む(include)。
アプリケーションに ICElib を結合する(link)には、-lICE を用いるものとする。
ProtocolSetup
を提起したクライアントと ProtocolReply
で応答するクライアントとを区別するため、ICE ライブラリで使用する名前には以下の接頭辞を付ける。
IcePo
- Ice Protocol Originator プロトコルの開始方
IcePa
- Ice Protocol Acceptor プロトコルの受理方
二者のクライアントが特定のプロトコルに則ったメッセージを交換し合うには、双方とも同プロトコルを ICE ライブラリに登録していなければならない。登録を通じて両者は、同プロトコルに対する主命令コードを取得し、メッセージ処理や認証作業を行うコールバック を設定する。登録用の関数が二つ、別々に用意されている。
一つは ProtocolSetup
を提起する側で用いるもの。
一つは ProtocolReply
で応答する側が用いるもの。
両クライアントによる ICE 接続の確立に先んじてプロトコルの登録を行うのが望ましい。プロトコルの登録が ICE 接続の成立後に行われる場合、プロトコルが未だ登録されていない内に同プロトコルの ProtocolSetup
が届いてしまうという事態も起こり得る。ICE 接続の成立前にプロトコルを登録することが不可能であれば、先の競合条件が生じないよう、適当な予防策を講じるべきである。
関数 IceRegisterForProtocolSetup
は、ProtocolSetup
を提起するクライアントが使用する。
int IceRegisterForProtocolSetup(
const char *protocol_name, const char *vendor, const char *release, int version_count, IcePoVersionRec *version_recs, int auth_count, const char **auth_names, IcePoAuthProc *auth_procs, IceIOErrorProc io_error_proc)
;
protocol_name |
登録するプロトコルの名前を表す文字列。 |
vendor |
開発者を表す文字列。意味は同プロトコルで定める。 |
release |
公開版を表す文字列。意味は同プロトコルで定める。 |
version_count |
同プロトコルの使用可能な版の数。 |
version_recs |
版番号とそれに対応するコールバックの組の配列。 |
auth_count |
使用可能な認証方式の数。 |
auth_names |
使用可能な認証方式の名前の配列。 |
auth_procs |
認証を行うコールバックの配列。各認証方式に一つづつ。 |
io_error_proc |
入出力エラーのハンドラ(処理器)、もしくは NULL。 |
関数 IceRegisterForProtocolSetup
は、成功すれば未使用の主命令コードを、エラーが起きれば -1 を返す。プロトコルを実際に利用できる状態にするには、この主命令コードを付して関数 IceProtocolSetup
を呼び出す必要がある。プロトコルが一度有効になった後、同プロトコルに基づく全てのメッセージは、この主命令コードを指定して送信するものとする。
一つのプロトコル・ライブラリで同一プロトコルの複数の版を運用することも可能である。引数 version_recs には、そのプロトコルの利用可能な版を、優先度に関して降順に並べる。一つ一つの版の情報(version record)は、プロトコルの版番号の上位(major version)、版番号の下位(minor version)及び受け取ったメッセージを処理するためのコールバック関数から成る。
typedef struct {
int major_version;
int minor_version;
IcePoProcessMsgProc process_msg_proc;
} IcePoVersionRec;
ProtocolSetup
を提起したクライアントによって受信されるメッセージ群を処理するのは、コールバック関数 IcePoProcessMsgProc
の仕事である。更なる情報は、メッセージを処理するコールバック を見よ。
プロトコルが利用可能な状態になる前の段階で認証を要求することもできる。プロトコル・ライブラリは、自身の対応し
ている認証方式を ICE ライブラリに登録しておかなければならない。引数 auth_names と引数 auth_procs
には、それぞれ、認証方式の名前とそれを実行するコールバックを、優先度に関して降順に列挙する。コールバック関数 IcePoAuthProc
についての情報は、認証方式 を見よ。
コールバック IceIOErrorProc
は、ICE 接続が予期せぬ形で途切れた場合に呼び出される。そのような事態の発生を知る必要がなければ、io_error_proc に NULL を渡すものとする。詳しくは、エラーの処理 を参照。
関数 IceRegisterForProtocolReply
は、ProtocolSetup
に対して ProtocolReply
で応答するクライアントによって使用される。
int IceRegisterForProtocolReply(
const char *protocol_name, const char *vendor, const char *release, int version_count, IcePaVersionRec *version_recs, int auth_count, const char **auth_names, IcePaAuthProc *auth_procs, IceHostBasedAuthProc host_based_auth_proc, IceProtocolSetupProc protocol_setup_proc, IceProtocolActivateProc protocol_activate_proc, IceIOErrorProc io_error_proc)
;
protocol_name |
登録するプロトコルの名前を表す文字列。 |
vendor |
開発者を表す文字列。意味は同プロトコルで定める。 |
release |
公開版を表す文字列。意味は同プロトコルで定める。 |
version_count |
同プロトコルの使用可能な版の数。 |
version_recs |
版番号とそれに対応するコールバックの組の配列。 |
auth_count |
使用可能な認証方式の数。 |
auth_names |
使用可能な認証方式の名前の配列。 |
auth_procs |
認証を行うコールバックの配列。各認証方式に一つづつ。 |
host_based_auth_proc |
ホスト名に基づく認証のためのコールバック。 |
protocol_setup_proc |
|
protocol_activate_proc |
|
io_error_proc |
入出力エラーのハンドラ(処理器)、もしくは NULL。 |
IceRegisterForProtocolReply
は、成功すれば未使用の主命令コードを、エラーが起きれば -1 を返す。返ってきた主命令コードは、このプロトコルに則って送信される以後のメッセージ全てで使用するものとする。
一つのプロトコル・ライブラリで同一プロトコルの複数の版を運用することも可能である。引数 version_recs には、そのプロトコルの利用可能な版を、優先度に関して降順に並べる。一つ一つの版の情報(version record)は、プロトコルの版番号の上位(major version)、版番号の下位(minor version)及び受け取ったメッセージを処理するためのコールバック関数から成る。
typedef struct {
int major_version;
int minor_version;
IcePaProcessMsgProc process_msg_proc;
} IcePaVersionRec;
ProtocolSetup
を受理したクライアントに届けられるメッセージ群を処理するのは、コールバック IcePaProcessMsgProc
の仕事である。詳しくは メッセージを処理するコールバック を見よ。
プロトコルが利用可能な状態になる前の段階で認証を要求することもできる。プロトコル・ライブラリは、自身の対応し
ている認証方式を ICE ライブラリに登録しておかなければならない。引数 auth_names と引数 auth_procs
には、それぞれ、認証方式の名前とそれを実行するコールバックを、優先度に関して降順に列挙する。コールバック IcePaAuthProc
についての情報は、認証方式 を見よ。
認証に失敗し、且つ ProtocolSetup
を提起しているクライアントが認証を要求していない場合、開始方クライアントのホスト名を付してコールバック IceHostBasedAuthProc
を呼び出す。もしこのコールバックが True
を返せば、たとえ元々の認証に失敗していたとしても、ProtocolSetup
は成功となる。True
しか返さない IceHostBasedAuthProc
を登録することで、実質的に認証機能が無効になることに注意する。ホスト名に基づく認証を一切許可しない場合には、引数 host_based_auth_proc に NULL を渡すものとする。
typedef Bool (*IceHostBasedAuthProc)(
char *host_name)
;
host_name |
|
引数 host_name は protocol/hostname の形をとる文字列である。protocol の部分には、{tcp, decnet, local} の何れか一つが入る。
ProtocolSetup
メッセージの処理と認証作業がコールバックによって舞台裏で実行されることから、プロトコル・ライブラリには ProtocolSetup
の完了を知るための仕組みが必要になる。この仕組みは二つの段階に分かれる。第一段階では、認証を成功裡に終えてから ICE ライブラリが ProtocolReply
を送信するまでの間に、コールバック IceProtocolSetupProc
を呼び出す。設定中のプロトコルで必要な資源はこの時に割り当てる。IceProtocolSetupProc
の戻り値が成功を意味するものであれば、ICE ライブラリは ProtocolReply
を送信し、それに続いて同ライブラリにてコールバック IceProtocolActivateProc
を呼び出す。それ以外の場合は、ProtocolSetup
に対する返答として、相手方のクライアントへエラーが送られる。
IceProtocolActivateProc
は必須のコールバックではない。ProtocolReply
の直後にプロトコル・ライブラリでメッセージを生成する場合に限って此れを登録する。このコールバックが不要であれば、protocol_activate_proc に NULL を渡す。
typedef Status (*IceProtocolSetupProc)(
IceConn ice_conn, int major_version, int minor_version, char *vendor, char *release, IcePointer *client_data_ret, char **failure_reason_ret)
;
ice_conn |
ICE 接続オブジェクト。 |
major_version |
プロトコルの版番号の上位。 |
minor_version |
プロトコルの版番号の下位。 |
vendor |
開発者を表す文字列。プロトコルの開始方によって登録されたもの。 |
release |
公開版を表す文字列。プロトコルの開始方によって登録されたもの。 |
client_data_ret |
コールバックで設定するクライアント・データ。 |
failure_reason_ret |
失敗の原因。 |
引数 client_data_ret に格納されたポインタは、ICE 接続上で此のプロトコルに宛ててメッセージが届く度に、コールバック IcePaProcessMsgProc
に渡される。
vendor と release に渡される文字列は、用が済んだ時点で free
を用いて解放するものとする。
IceProtocolSetupProc
が不首尾に終わった場合、同コールバックは実値 0 の Status を返すとともに、failure_reason_ret に文字列領域を割り当て、そこに失敗の理由を格納する。この領域を解放するのは ICE ライブラリの仕事である。
コールバック IceProtocolActivateProc
は次のように定義されている。
ice_conn |
ICE 接続オブジェクト。 |
client_data |
コールバック |
コールバック IceIOErrorProc
は、ICE 接続が予期せぬ形で途切れた場合に呼び出される。そのような事態の発生を知る必要がなければ、io_error_proc に NULL を渡すものとする。詳しくは、エラーの処理 を参照。
アプリケーションは、(select
を通じて) ICE 接続上に未読のデータがあることを知った時、関数 IceProcessMessages
を呼び出す。メッセージの処理 を参照。IceProcessMessages
において 0 でない主命令コードの付いた ICE メッセージ・ヘッダを読み取った時( 0 は ICE プロトコルが使用する)、同関数は、メッセージの残りの部分を読み込み、開封し、場合によっては、処理するための関数を呼び出さなければならない。
ProtocolSetup
を提起したクライアントの下にメッセージが届いた場合、コールバック IcePoProcessMsgProc
を呼び出す。
typedef void (*IcePoProcessMsgProc)(
IceConn ice_conn, IcePointer client_data, int opcode, unsigned long length, Bool swap, IceReplyWaitInfo *reply_wait, Bool *reply_ready_ret)
;
ice_conn |
ICE 接続オブジェクト。 |
client_data |
同 ICE 接続において此のプロトコルに紐付けられているクライアント・データ。 |
opcode |
メッセージの従たる命令コード。 |
length |
ICE ヘッダ以降のメッセージの長さ(8 バイト単位)。 |
swap |
バイト順の交換が必要か否かを表すフラグ。 |
reply_wait |
呼出し元のクライアントが返答を待っているのか否かを表す。 |
reply_ready_ret |
|
ProtocolSetup
を受理したクライアントの下にメッセージが届いた場合、コールバック IcePaProcessMsgProc
を呼び出す。
typedef void (*IcePaProcessMsgProc)(
IceConn ice_conn, IcePointer client_data, int opcode, unsigned long length, Bool swap)
;
ice_conn |
ICE 接続オブジェクト。 |
client_data |
同 ICE 接続において此のプロトコルに紐付けられているクライアント・データ。 |
opcode |
メッセージの従たる命令コード。 |
length |
ICE ヘッダ以降のメッセージの長さ(8 バイト単位)。 |
swap |
バイト順の交換が必要か否かを表すフラグ。 |
メッセージを読み込むためのマクロが定義されているので、上記の両コールバックはこれを利用する(「ICE メッセージを読む」を参照)。バイト順の交換が必要になることもあり得るという点に注意する。ICE ヘッダの length フィールドのバイト順交換は、必要があれば ICElib にて行われる。
両コールバックにおいて、引数 client_data には ProtocolSetup
の際に登録したクライアント・データへのポインタが格納されている。IcePoProcessMsgProc
の場合、クライアント・データは IceProtocolSetup
呼出しの中で設定される(訳註:SMlib では SmcConn がクライアント・データとして渡される)。IcePaProcessMsgProc
の場合、クライアント・データはコールバック IceProtocolSetupProc
の中で設定される(訳註:SMlib では SmsConn がクライアント・データとして渡される)。
コールバック IcePoProcessMsgProc
では、引数 reply_wait を確認する必要がある。もし replay_wait が NULL であれば、ICE
ライブラリは次のように判断する。即ち、この関数はコールバックを通じてクライアントにメッセージを届けるものと見做される。例えば、ここでのメッセージ
がセッション管理における「Save Yourself」メッセージであるとすると、当関数はコールバック経由でクライアントに「Save
Yourself」を通知するということである。このようなコールバックが実際にどのように定義されるかは、実装次第である。
一方、reply_wait が NULL でない場合、クライアントは先に自身が送信したメッセージに対する返信もしくはエラー報告を待ち受けているものと見做される。reply_wait は IceReplyWaitInfo
型である。
typedef struct {
unsigned long sequence_of_request;
int major_opcode_of_request;
int minor_opcode_of_request;
IcePointer reply;
} IceReplyWaitInfo;
IceReplyWaitInfo
構造体にはメッセージの主/従命令コードと通し番号が入っているが、これは、現在待ち受けている返信が為される所以となったメッセージのものである。同構造体には、返信メッセージが書き込まれる領域へのポインタも含まれている(プロトコル・ライブラリにおいて、この IcePointer
を返信用の適当な型に読み替える)。大抵、返信メッセージには固定長の部分が存在し、そして、この固定長データ部分を内部に保持する構造体へのポインタは、返信を待っているクライアントが用意する。可変長のデータがある場合、コールバック IcePoProcessMsgProc
において追加の記憶領域が確保され、その領域へのポインタが先の固定長構造体の中に格納される。もしデータが丸ごと可変長であれば(例えば可変長文字列一
つ)、返信を待ち受ける方のクライアントは、ポインタ一つを保持できる固定長領域へのポインタを渡すだけで良い。そして、コールバック IcePoProcessMsgProc
が記憶領域を新たに確保し、その領域へのポインタを(渡されたポインタの指し示す固定長領域に)書き込む。返信を受け取ったクライアントは、自身のために割り当てられた記憶領域の解放作業を引き受けるものとする。
reply_wait が NULL ではなく、且つ IcePoProcessMsgProc
において同 reply_wait に対する返信もしくはエラー報告がある場合(つまりコールバックが生成されなかった場合)、引数 reply_ready_ret を True
に設定する。エラーを返すのは、待ち受けられている返信にそのエラーが直接関連している時だけである、という点に注意する。それ以外の時は、IcePoProcessMsgProc
は内部でエラーを処理するか、実装ライブラリのエラー・ハンドラ(処理器)を呼び出す。
reply_wait が NULL の場合は reply_ready_ret も NULL であろうから、このポインタに如何なる値も書き込まないよう気をつけなければならない。
一方、コールバック IcePaProcessMsgProc
では、クライアントへメッセージを渡すにあたって、常にコールバックを利用する。例えば、ここでのメッセージがセッション管理における「Interact
Request」メッセージであるとすると、この関数ではコールバック経由でクライアントに「Interact
Request」を通知することになる。
コールバック IcePaProcessMsgProc
が IcePoProcessMsgProc
のように reply_wait
を利用しないのは次の理由による。即ち、サーバとして振舞うプロセスは、返信を待って他の入力を弾くわけにはいかないからである(接続を試みる方のクライ
アントが異常な動作をした結果、際限なくメッセージをブロックする(返信が来るまで関数から戻らない)ようになると、他のクライアントとは通信できなく
なってしまう)。
先に述べたように、プロトコル・ライブラリは、自身が対応している認証方式を ICE ライブラリに登録しなければならない。各認証方式に対して、二つのコールバックを登録することができる。
一つは、ProtocolSetup
を提起する側の処理を行うコールバック。
一つは、この要求を受理もしくは拒否する側の処理を行うコールバック。
IcePoAuthProc
は、ProtocolSetup
を提起したクライアントのために呼び出されるコールバックである。このコールバックは、他のクライアントから送られてくる先頭メッセージ
「Authentication Required」もしくは後続メッセージ「Authentication Next
Phase」に応えることができなければならない。
typedef IcePoAuthStatus (*IcePoAuthProc)(
IceConn ice_conn, IcePointer *auth_state_ptr, Bool clean_up, Bool swap, int auth_datalen, IcePointer auth_data, int *reply_datalen_ret, IcePointer *reply_data_ret, char **error_string_ret)
;
ice_conn |
ICE 接続オブジェクト。 |
auth_state_ptr |
認証のコールバック手続きで使用する状態情報へのポインタ。 |
clean_up |
|
swap |
|
auth_datalen |
認証データのバイト長。 |
auth_data |
認証者からのデータ。 |
reply_datalen_ret |
この関数の戻り値たる返信データのバイト長。 |
reply_data_ret |
この関数で返される返信データ。 |
error_string_ret |
認証手続きの関数中でエラーが発生した場合、同関数はエラー文を割り当てた上で返り値とする。 |
認証方式によっては、作業の完遂に複数の段階を要することもある。その為、クライアントの認証作業中に IcePoAuthProc
を複数回呼び出すことがあり得る。そして、その複数の呼出しの合間にも保持し続けなければならない状態情報があるであろう。各 ProtocolSetup
の開始時点では *auth_state_ptr は NULL
であり、この関数(IcePoAuthProc)を通じて状態の初期化と同ポインタの設定を行う。このポインタは、後続の本コールバックの呼出しにおい
て、先行コールバックが記録した状態情報を取得するのに用いられる。
必要であれば、関数 IceConnectionString
を呼び出すことで、ProtocolSetup
を受理するクライアントのネットワーク ID を取得することができる。
free
を用いて reply_data_ret と error_string_ret の両ポインタを解放するのは ICElib の仕事である。
auth_data のポインタが揮発性の(volatile)記憶領域を指していることもあり得る。コールバックの呼出し完了以後もデータを保持する必要があれば、忘れずに複製を作っておく。
IcePoAuthProc
は、次の四つの値の何れか一つを返す。
IcePoAuthHaveReply
- 返信は入手可能。
IcePoAuthRejected
- 認証が拒否された。
IcePoAuthFailed
- 認証に失敗した。
IcePoAuthDoneCleanup
- 片付けを終えた。
IcePaAuthProc
は、ProtocolSetup
を受信したクライアントのために呼び出されるコールバックである。
typedef IcePaAuthStatus (*IcePaAuthProc)(
IceConn ice_conn, IcePointer *auth_state_ptr, Bool swap, int auth_datalen, IcePointer auth_data, int *reply_datalen_ret, IcePointer *reply_data_ret, char **error_string_ret)
;
ice_conn |
ICE 接続オブジェクト。 |
auth_state_ptr |
認証のコールバック手続きで使用する状態情報へのポインタ。 |
swap |
|
auth_datalen |
プロトコル開始方からの認証データのバイト長。 |
auth_data |
プロトコル開始方からの認証データ。 |
reply_datalen_ret |
この関数の戻り値たる認証データの長さ。 |
reply_data_ret |
この関数の戻り値たる認証データ。 |
error_string_ret |
認証の拒否もしくは蹉跌に際し、戻り値としてエラー文が格納される。 |
認証方式によっては、作業の完遂に複数の段階を要することもある。その為、クライアントの認証作業中に IcePaAuthProc
を複数回呼び出すことがあり得る。そして、その複数の呼出しの合間にも保持し続けなければならない状態情報があるであろう。各 ProtocolSetup
の開始時点では、auth_datalen は 0、*auth_state_ptr は NULL
であり、この関数(IcePaAuthProc)を通じて状態の初期化とポインタの設定を行う。このポインタは、後続の本コールバックの呼出しにおいて、
先行コールバックが記録した状態情報を取得するのに用いられる。
必要であれば、関数 IceConnectionString
を呼び出すことで、ProtocolSetup
を受理するクライアントのネットワーク ID を取得することができる。
auth_data のポインタが揮発性の(volatile)記憶領域を指していることもあり得る。コールバックの呼出し完了以後もデータを保持する必要があれば、忘れずに複製を作っておく。
reply_data_ret と error_string_ret の両ポインタを伝送し、且つ free
を用いて解放するのは、ICElib の仕事である。
IcePaAuthProc
は、次の四つの値の何れか一つを返す。
IcePaAuthContinue
- 認証を続ける(あるいは始める)。
IcePaAuthAccepted
- 認証に成功した。
IcePaAuthRejected
- 認証を拒否した。
IcePaAuthFailed
- 認証に失敗した。
二つのクライアントの間で ICE 接続を確立するには、一方に接続を待ち受けるクライアントが、他方に接続を提起するクライアントが存在しなければならない。大多数のクライアントは接続を提起する側なので、まずその方から取り上げる。
ICE 接続を待ち受けている他のクライアントとの間に接続を開設するには、IceOpenConnection
を用いる。
IceConn IceOpenConnection(
char *network_ids_list, IcePointer context, Bool must_authenticate, int major_opcode_check, int error_length, char *error_string_ret)
;
network_ids_list |
相手のクライアントのネットワーク ID(複数可)を記す。 |
context |
不透明なオブジェクトへのポインタもしくは NULL。これを用いて ICE 接続の共有が可能か判断する(後述)。 |
must_authenticate |
|
major_opcode_check |
新しい ICE 接続の生成を義務づけるために使用する(後述)。 |
error_length |
引数 error_string_ret の長さ。 |
error_string_ret |
null 文字終端のエラーメッセージを返す(もし存在すれば)。引数 error_string_ret は利用者の用意した記憶領域を参照する。error_length の数値分のバイトしか使用しない。 |
IceOpenConnection
は、成功すれば、不透明な(opaque) ICE 接続オブジェクトを返す。失敗すれば、NULL を返す。
引数 network_ids_list には、コンマで区切ったネットワーク ID 群の並びを渡す。まず先頭のネットワーク ID を使って接続を試みる。これが失敗すれば、二番目のネットワーク ID を使って試行し、これが失敗すれば以下同様。各ネットワーク ID は次の書式をとる。
tcp/<hostname>:<portnumber> | もしくは |
decnet/<hostname>::<objname> | もしくは |
local/<hostname>:<path> |
大抵のプロトコル・ライブラリは、内部で IceOpenConnection
を呼び出す、ある種の開設関数(open function)を備えることになるであろう。IceOpenConnection
を呼び出した時、既設の ICE 接続の利用が認められることもある(接続相手のクライアントが同一の場合)。一方、ICE 接続の共用が望ましくないこともある。
引数 context によって、ICE 接続の共用の可否を判断する。context が NULL であれば、当関数の呼出者は常に接続の共有を試みる。context が NULL でなければ、呼出方は、自身が指定したものとは異なる、NULL でない context と結びついた既設の ICE 接続を用いない。
加えて、major_opcode_check に 0 でない主命令コードの値が渡された場合、既設の ICE 接続でその主命令コードが使用されていない時に限って、同接続を利用する。これを使えば、二つのクライアントの間で、同一プロトコルを用いた ICE 接続を複数設けるよう指示することも可能である。
認証に必要な処理は ICE ライブラリの内部で行われる。認証データを取得する方法は実装によって異なる。[1]
IceOpenConnection
の呼出しが終わると、クライアントは ProtocolSetup
を送受信できるようになる(IceRegisterForProtocolSetup
を呼び出している方は送信、IceRegisterForProtocolReply
を呼び出している方は受信が可能)。
ICE 接続を受け入れようとするクライアントは、接続要求を察知できるように、まず IceListenForConnections
または IceListenForWellKnownConnections
を呼び出さなければならない。これらの関数の結果、不透明な待受けオブジェクト(opaque "listen"
objects)の配列が取得できる。利用可能な伝送方式(transport method)の種類一つにつき(例、Unix
Domain、TCP、DECnet など)、一つのオブジェクトが割り当てられる。
通常、クライアントは、各伝送方式中の利用可能な名前(訳註:ポート番号、オブジェクト名、経路名)の生成と、待受けオブジェクト群(listen objects)の取得を ICElib に依頼する。そうしたクライアントは次に、IceComposeNetworkIdList
を用いて ICElib
が定めた名前(訳註:ポート番号、オブジェクト名、経路名)を取り出し、接続開設を試みる他のクライアントから、それらの名前が利用できるようにする。時
には、予め決められた伝送オブジェクト名(transport object
names)で接続を待ち受けなければならないこともあろう。そうしたクライアントは、IceListenForWellKnownConnections
を用いて、待受けオブジェクト群(listen objects)の名前(訳註:ポート番号、オブジェクト名、経路名)を指定することができる。
Status IceListenForConnections(
int *count_ret, IceListenObj **listen_objs_ret, int error_length, char *error_string_ret)
;
count_ret |
生成された待受けオブジェクト(listen objects)の数を返す。 |
listen_objs_ret |
不透明な待受けオブジェクト(opaque listen objects)へのポインタの配列を返す。 |
error_length |
引数 error_string_ret の長さ。 |
error_string_ret |
エラーがあれば、null 文字終端のエラーメッセージを返す。ポインタ error_string_ret は利用者の用意した領域を指す。error_length の数値分のバイト数しか使用されない。 |
IceListenForConnections
の戻り値は、失敗すれば 0、成功すれば正の値である。
Status IceListenForWellKnownConnections(
char *port_id, int *count_ret, IceListenObj **listen_objs_ret, int error_length, char *error_string_ret)
;
port_id |
接続を待つアドレスのポート識別子を渡す。文字列中には、スラッシュ("/")やコンマ(".")が含まれてはいけない。これらは将来の利用に備えて使わずにおく。 |
count_ret |
生成された待受けオブジェクト(listen objects)の数を返す。 |
listen_objs_ret |
不透明な待受けオブジェクト(opaque listen objects)へのポインタの配列を返す。 |
error_length |
引数 error_string_ret の長さ。 |
error_string_ret |
エラーがあれば、null 文字終端のエラーメッセージを返す。ポインタ error_string_ret は、利用者の用意した記憶領域を指す。error_length の数値分のバイト数しか使用されない。 |
IceListenForWellKnownConnections
は、既知の伝送方式(transport)の一つ一つを port_id の頭に付加する方法で、ネットワーク ID
の一覧を構成し、その結果を用いて待受けオブジェクト群(listen objects)を作成する。port_id には、ICE ネットワーク ID
中のポート番号(portnumber)、オブジェクト名(objname)、もしくは経路(path)の部分が入る。あるネットワーク ID
に対して待受けオブジェクト(listen object)が作成できなかった場合、そのネットワーク ID
は無視する。一つも待受けオブジェクトが作成されなければ、IceListenForWellKnownConnections
は失敗を意味する戻り値を返す。
IceListenForWellKnownConnections
の戻り値は、失敗すれば 0、成功すれば正の値である。
待受けオブジェクトを閉鎖・解放するには、IceFreeListenObjs
を用いる。
count |
待受けオブジェクト(listen object)の数。 |
listen_objs |
待受けオブジェクト群(listen objects)。 |
待受けオブジェクト(listen object)に対する新たな接続を検出するには、その待受けオブジェクトに結び付けられている記述子に対して、select
を使用する。
記述子を取得するには、IceGetListenConnectionNumber
を用いる。
listen_obj |
待受けオブジェクト(listen object)。 |
待受けオブジェクトに結び付けられたネットワーク ID の文字列表現を取得するには、IceGetListenConnectionString
を用いる。
listen_obj |
待受けオブジェクト(listen object)。 |
ネットワーク ID は次の書式で記述される。
tcp/<hostname>:<portnumber> | もしくは |
decnet/<hostname>::<objname> | もしくは |
local/<hostname>:<path> |
ネットワーク ID 群をコンマで区切って並べた文字列(IceOpenConnection
に渡せる形式)を作るには、IceComposeNetworkIdList
を用いる。
count |
待受けオブジェクト(listen objects)の数。 |
listen_objs |
待受けオブジェクト群(listen objects)。 |
ICE
接続の開設を試みた時、認証に失敗し、且つ開始方クライアントが認証を要求していない場合、開始方クライアントに接続の最後の機会を与えるべく、ホスト名
に基づく認証手続き(host based authentication
procedure)を呼び出すことができる。各待受けオブジェクトには、この種のコールバックが一つ備わっている。関数 IceSetHostBasedAuthProc
を用いて、このコールバックの設定を行う。
IceListenObj |
待受けオブジェクト(listen object)。 |
host_based_auth_proc |
ホスト名に基づく認証手続き。 |
各待受けオブジェクトは、初期状態において、ホスト名に基づく認証手続きを何ら有していない。既にホスト名認証が 設定されている場合、引数 host_based_auth_proc に NULL を渡すことによって、同認証手続きを消去することができる。
host_name |
ICE 接続の開設を試みたクライアントのホスト名。 |
引数 host_name には「protocol/ hostname」の形をとる文字列を渡す。ここでの「protocol」には、{tcp、decnet、local} の何れか一つが入る。
IceHostBasedAuthProc
から True
が返れば、たとえ元々の認証に失敗していても、接続は許可される。常に True
を返す IceHostBasedAuthProc
を登録することで、認証機能を実質的に無効にすることができる点に注意する。
ホスト名に基づく認証は ProtocolSetup
の段階でも使用可能である。この段階で使うコールバックは、関数 IceRegisterForProtocolReply
で指定する(プロトコルの登録を見よ)。
IceListenForConnections
で取得した待受けオブジェクト(listen object)にて接続の試みを検知した後、IceAcceptConnection
を呼び出す。この関数は、新しく不透明な ICE 接続オブジェクト返す。
listen_obj |
新たな接続を検知した待受けオブジェクト(listen object)。 |
status_ret |
戻り値たる状態情報。 |
引数 status_ret は、次の値のどれか一つに設定される。
IceAcceptSuccess
- 受入れ作業は成功し、この関数は新しい接続オブジェクトを返す。
IceAcceptFailure
- 受入れ作業は失敗し、この関数は NULL を返す。
IceAcceptBadMalloc
- 記憶領域の確保が失敗し、この関数は NULL を返す。
一般に、新しい接続を検知するには、待受けオブジェクトに結び付けられたファイル記述子に対して select
を実行する。新しい接続が見つかった時は、関数 IceAcceptConnection
を呼び出す。IceAcceptConnection
は、仮設状態の新 ICE 接続を返すことがある。これは、接続が有効になる前の段階で、認証を行うことがあるためである。ICE
ライブラリは仮設状態の接続が有効になるまでの間、他の接続要求を弾くわけにはいかないので(接続を試みるクライアントが不適切な動きをすると、際限なく
接続要求をブロックしてしまう(接続が有効になるまで関数から返らない))、アプリケーション側で接続が有効な状態に変わるのを待たなければならない。
次の擬似コードによって、接続を受理する過程を例示する。
new_ice_conn = IceAcceptConnection (listen_obj, &accept_status); if (accept_status != IceAcceptSuccess) { ファイル記述子を閉じて戻る } status = IceConnectionStatus (new_ice_conn); time_start = time_now; while (status == IceConnectPending) { select() on {new_ice_conn, all open connections} for (each ice_conn in the list of open connections) if (data ready on ice_conn) { status = IceProcessMessages (ice_conn, NULL, NULL); if (status == IceProcessMessagesIOError) IceCloseConnection(ice_conn); } if data ready on new_ice_conn { /* * IceProcessMessages は、接続が仮設でなくなる * まで呼び出される。これによって、接続設定要求 * と認証手続きを処理する。 */ IceProcessMessages ( new_ice_conn, NULL, NULL); status = IceConnectionStatus (new_ice_conn); } else { if (time_now - time_start > MAX_WAIT_TIME) status = IceConnectRejected; } } if (status == IceConnectAccepted) { Add new_ice_conn to the list of open connections } else { IceCloseConnection new_ice_conn }
IceAcceptConnection
が呼び出され、接続が有効になると、クライアントは ProtocolSetup
を送受信できるようになる(IceRegisterForProtocolSetup
を呼び出している方は送信、IceRegisterForProtocolReply
を呼び出している方は受信が可能)。
IceOpenConnection
や IceAcceptConnection
で作成された ICE 接続を閉じるには、IceCloseConnection
を用いる。
ice_conn |
閉鎖する ICE 接続。 |
ある接続を実際に閉じるには、以下の条件が満たされなければならない、
同 ICE 接続の開設参照数(open reference count)が 0 に達しなければならない。IceOpenConnection
が呼び出された時、まず既に開かれている ICE 接続の利用を試みる。既存の接続が利用可能であれば、IceOpenConnection
は同接続の開設参照数を一つ増やす。そのため、ある ICE 接続を閉じるには、IceOpenConnection
の各呼出しに対して、それに応じた IceCloseConnection
が一つ呼び出されなければならない。このような接続は、最後の IceCloseConnection
を受けて初めて切断可能になる。
同 ICE 接続の実効プロトコル数(active protocol count)が 0 に達しなければならない。同接続において ProtocolSetup
が成功する度に、実効プロトコル数が一つ増える。クライアントは、同接続上の使う予定のなくなったプロトコルに対して、関数 IceProtocolShutdown
を呼び出し、これによって実効プロトコル数を一つ減らす(プロトコルの設定と終了を見よ)。
同 ICE 接続において終了交渉(shutdown negotiation)が可能である場合、接続相手のクライアントが接続切断に同意しなければならない。
IceCloseConnection
は、次の値の何れか一つを返す。
IceClosedNow
- ICE 接続は、この時点で閉鎖された。看視手続き(watch procedures)が呼び出され、接続資源が解放された。
IceClosedASAP
- ICE 接続上で入出力エラーが発生したが、まだ IceProcessMessages
の入れ籠の内から IceCloseConnection
が呼び出されている最中である。この時点で看視手続きは既に呼び出されているが、接続は(訳註:まだ解放されておらず、これから)「できる限り早く」解放される(IceProcessMessages
の入れ籠の層が 0 に達し、同関数が IceProcessMessagesConnectionClosed
を返した時)。
IceConnectionInUse
- 他の生きたプロトコルがこの接続を使用しているため、今回は切断されなかった。
IceStartedShutdownNegotiation
- この時点では接続は閉鎖されなかった。そして、ICE 接続の相手方クライアントとの終了交渉(shutdown negotiation)が始まった。実際に接続が切断された時は、IceProcessMessages
が IceProcessMessagesConnectionClosed
を返す。
ICE 接続の相手方クライアントが終了交渉(shutdown negotiation)を提起することなく接続を断ったことが分かった時は、関数 IceSetShutdownNegotiation
を呼び出して、終了交渉を行わない設定に切り替える。これによって、IceCloseConnection
が壊れた接続に対して書き込んでしまうことを防ぐ。
ice_conn |
有効な ICE 接続オブジェクト。 |
negotiate |
|
ICE 接続の終了交渉に関する設定を調べるには、IceCheckShutdownNegotiation
を用いる。
ice_conn |
有効な ICE 接続オブジェクト。 |
IceCheckShutdownNegotiation
が True
を返すのは、引数で指定した接続において終了交渉が行われるよう設定されている時である。そうでない場合、False
が返る。どの接続も、初期状態では交渉を行う設定になっている。この設定は、関数 IceSetShutdownNegotiation
を使わなければ変更できない。
看視手続き(watch procedure)を新たに登録するには、IceAddConnectionWatch
を用いる。登録された看視手続きは、ICElib が IceOpenConnection
や IceAcceptConnection
によって新しい接続を開く度に、あるいは IceCloseConnection
によって接続を閉じる度に、呼び出されることになる。
watch_proc |
ICElib で接続が開閉される時に呼び出される看視手続き(watch procedure)。 |
client_data |
このポインタは看視手続き呼出し時にその引数として渡される。 |
IceAddConnectionWatch
の戻り値は、失敗すれば 0、成功すれば正の値である。
幾度かの IceOpenConnection
の呼出しの結果、同一の ICE 接続が共用されることもあるという点に注意する。このような場合、看視手続きは、最初に接続が確立された時(認証成功後)にしか呼び出されない。同様に、接続が共有されている可能性があるので、IceCloseConnection
を通じて実際に接続が切断された時に限り、看視手続きが呼び出される(IceConn の解放直前)。
新しい接続が作成された時に select mask にファイル記述子を加え、接続が破棄された時にファイル記述子を取り除くアプリケーションにとって、この看視手続きはとても役に立つものである。接続が共 有されている可能性があるので、select mask に対して何時ファイル記述子を加えたり除いたりすべきなのかを、看視手続き無しに知るのは難しい。
ICE ライブラリに複数の看視手続き(watch procedures)を登録できる。手続きが複数ある時の呼出し順序は、何ら想定すべきでない。
看視手続き登録の時点において、ICE ライブラリに一つでも ICE 接続が作成されていれば、そうした ICE 接続の一つ一つに対して、直ちに同看視手続きが呼び出される。その際、引数 opening に True
を渡す。
看視手続きの関数型は IceWatchProc
である。
typedef void (*IceWatchProc)(
IceConn ice_conn, IcePointer client_data, Bool opening, IcePointer *watch_data)
;
ice_conn |
開設あるいは閉鎖される ICE 接続。この接続と結び付いたファイル記述子を取得するには、 |
client_data |
|
opening |
接続が開かれる際の呼出しでは |
watch_data |
クライアント・データへのポインタを保存するために使用できる。 |
opening が True
の時、クライアントは、接続終了まで保持する必要のあるデータを指すように、ポインタ *watch_data を設定する。看視手続きはその後、opening に False
を渡して、再び呼び出される。
看視手続きを削除するには、IceRemoveConnectionWatch
を用いる。
watch_proc |
|
client_data |
|
ある ICE 接続においてプロトコル一つを有効化するには、IceProtocolSetup
を用いる。
IceProtocolSetupStatus IceProtocolSetup(
IceConn ice_conn, int my_opcode, IcePointer client_data, Bool must_authenticate, int *major_version_ret, int *minor_version_ret, char **vendor_ret, char **release_ret, int error_length, char *error_string_ret)
;
ice_conn |
有効な ICE 接続オブジェクト。 |
my_opcode |
設定するプロトコルの主命令コード(major opcode)。これは |
client_data |
このポインタで記録しているクライアント・データは、コールバック |
must_authenticate |
もし |
major_version_ret |
戻り値として、使用するプロトコルの版番号の上位が格納される。 |
minor_version_ret |
戻り値として、使用するプロトコルの版番号の下位が格納される。 |
vendor_ret |
vendor(開発者)を示す文字列。プロトコルの受理方が記す。 |
release_ret |
release(公開版)を示す文字列。プロトコルの受理方が記す。 |
error_length |
引数 error_string_ret の長さを示す。 |
error_string_ret |
エラーがあれば、null 文字終端のエラーメッセージを返す。引数 error_string_ret は利用者の用意した領域を参照する。error_length の数値分のバイト数しか使用しない。 |
文字列 vendor_ret と文字列 release_ret は、必要でなくなった時は free
を用いて解放するものとする。
IceProtocolSetup
は、次の値の何れか一つを返す。
IceProtocolSetupSuccess
- major_version_ret、minor_version_ret、vendor_ret、release_ret が設定された。
IceProtocolSetupFailure
もしくは IceProtocolSetupIOError
- 蹉跌の理由が error_string_ret に入っている。major_version_ret、minor_version_ret、vendor_ret、release_ret は設定されず。
IceProtocolAlreadyActive
- 引数で指定された ICE 接続において、このプロトコルは既に有効である。major_version_ret、minor_version_ret、vendor_ret、release_ret は設定されず。
ICE 接続上のあるプロトコルが最早使われなくなった時は、IceProtocolShutdown
を用いて ICE ライブラリにその旨を通知する。
ice_conn |
有効な ICE 接続オブジェクト。 |
major_opcode |
終了するプロトコルの主命令コード(major opcode)。 |
IceProtocolShutdown
の戻り値は、失敗すれば 0、成功すれば正の値である。
指定された主命令コードが登録されていないものであった場合、あるいは、指定された主命令コードを持つプロトコルが、指定された ICE 接続において一度も有効化されていない場合、IceProtocolShutdown
は失敗する。有効化された(activated)とは、同接続において ProtocolSetup
に成功した状態のことを指す。ICE では、各下位プロトコル(sub-protocol)がどのようにしてプロトコルの終了を提起するかについては、定めていないことに注意する。
ICE 接続上で受け取ったメッセージを処理するには、IceProcessMessages
を用いる。
IceProcessMessagesStatus IceProcessMessages(
IceConn ice_conn, IceReplyWaitInfo *reply_wait, Bool *reply_ready_ret)
;
ice_conn |
有効な ICE 接続オブジェクト。 |
reply_wait |
呼出し元のクライアントが返答を待っているのか否かを表す。 |
reply_ready_ret |
戻り値として |
IceProcessMessages
には、二つの使い方がある。
第一の使い方。クライアントは、メッセージを生成した後、その返答を得るまで繰り返し IceProcessMessages
を呼び出して、ブロック(入力待機)することができる。(訳註:使用例は X11R7.7/lib/libSM-1.2.1/src/sm_client.c がある。)
第二の使い方。ICE 接続上に読み込むべきデータが存在することを知らせる select
を受けて、クライアントは reply_wait に NULL を渡して IceProcessMessages
を呼び出す。ICE ライブラリはメッセージの全身(complete message)を 0 個以上処理できる。ブロックされないメッセージは(返答の入力待機が為されないメッセージは)、常にコールバックを呼び出して処理する。
IceReplyWaitInfo
構造体にはメッセージの主/従命令コードと通し番号が入っているが、これは、現在待ち受けている返信が為される所以となったメッセージのものである。同構造体には、返信メッセージが書き込まれる領域へのポインタも含まれている(プロトコル・ライブラリにおいて、この IcePointer
を返信用の適当な型に読み替える)。大抵、返信メッセージには固定長の部分が存在し、そして、この固定長データ部分を内部に保持する構造体へのポインタは、返信を待っているクライアントが用意する。可変長のデータがある場合、コールバック IcePoProcessMsgProc
において追加の記憶領域が確保され、その領域へのポインタが先の固定長構造体の中に格納される。もしデータが丸ごと可変長であれば(例えば可変長文字列一
つ)、返信を待ち受ける方のクライアントは、ポインタ一つを保持できる固定長領域へのポインタを渡すだけで良い。そして、コールバック IcePoProcessMsgProc
が記憶領域を新たに確保し、その領域へのポインタを(渡されたポインタの指し示す固定長領域に)書き込む。返信を受け取ったクライアントは、自身のために
割り当てられた記憶領域の解放作業を引き受けるものとする。(訳註:X11R7.7/lib/libICE-1.0.8/src/process.c
の場合、IceProcessMessages の内部では、主命令コード等に従って _IceProcessCoreMsgProc
型関数、IcePoProcessMsgProc 型関数、もしくは IcePaProcessMsgProc 型関数を呼び出している。)
typedef struct { unsigned long sequence_of_request; int major_opcode_of_request; int minor_opcode_of_request; IcePointer reply; } IceReplyWaitInfo;
reply_wait が NULL ではなく、且つ IceProcessMessages
において同 reply_wait に対する返信もしくはエラー報告がある場合(つまりコールバックが生成されなかった場合)、引数 reply_ready_ret を True
に設定する。
reply_wait が NULL であれば、この関数を呼び出した者は reply_ready_ret にも NULL を渡しているはずであり、このポインタには何も格納されないことが保証される。
IceProcessMessages
は次の値の何れか一つを返す。
IceProcessMessagesSuccess
- エラーは起きなかった。
IceProcessMessagesIOError
- 入出力エラーが発生した。この関数を呼び出した者は IceCloseConnection
を使用して、明示的に接続を閉じなければならない。
IceProcessMessagesConnectionClosed
- ICE 接続は既に切断されている(終了交渉の故に、あるいは IceProcessMessages
の入れ籠階層が 0 でない為に、接続の切断が遅れている)。ICE 接続資源は既に解放されているので、この時点で接続に対する操作を試みてはいけない。
ICE 接続の相手方クライアントに対して「Ping」メッセージを送信するには、IcePing
を用いる。
ice_conn |
有効な ICE 接続オブジェクト。 |
ping_reply_proc |
Ping の応答が届いた時に呼び出すコールバック。 |
client_data |
このポインタはコールバック |
IcePing
は失敗すれば 0 を、成功すれば正の値を返す。
IceProcessMessages
では Ping の応答を処理するために、IcePingReplyProc
を呼び出す。
ice_conn |
有効な ICE 接続オブジェクト。 |
client_data |
|
IceConnectionStatus
は ICE 接続の状態値を返す。戻り値には以下のものがある。
IceConnectPending
- 接続は未だ有効ではない(つまり、認証作業中である)。これは IceAcceptConnection
によって作成された接続に対してしか意味を持たない。
IceConnectAccepted
- 接続は受け入れられた。これは IceAcceptConnection
によって作成された接続に対してしか意味を持たない。
IceConnectRejected
- 接続は拒否された(つまり、認証に失敗した)。これは IceAcceptConnection
によって作成された接続に対してしか意味を持たない。
IceConnectIOError
- 引数で指定された接続において、入出力エラーが発生した。
IceVendor
は、引数で指定した接続の ICE ライブラリの開発者識別文字列を返す。取得した文字列は、用が済んだところで、free
を呼び出して解放する。
IceRelease
は、同接続の ICE ライブラリの公開版番号識別文字列を返す。取得した文字列は、用が済んだところで、free
を呼び出して解放する。
IceProtocolVersion
は、引数で指定した接続において用いられている ICE プロトコルの版番号の上位(major version)を返す。
IceProtocolRevision
は、引数で指定した接続において用いられている ICE プロトコルの版番号の下位(minor version)を返す。
IceConnectionNumber
は、引数で指定された ICE 接続のファイル記述子を返す。
IceConnectionString
は、接続を受理した方のクライアントのネットワーク ID を返す。取得した文字列は、用が済んだところで、free
を呼び出して解放する。
IceLastSentSequenceNumber
は、引数で指定された ICE 接続において最後に送信されたメッセージの通し番号を返す。
IceLastReceivedSequenceNumber
は、引数で指定された ICE 接続において最後に受信されたメッセージの通し番号を返す。
IceSwapping
は、引数で指定された ICE 接続において、メッセージを読み込む際にバイト順の交換が必要である場合、True
を返す。
IceGetContext
は、IceOpenConnection
で作成された接続に結び付けられている文脈(context)を返す。(訳註:X11R7.7/lib/libICE-1.0.8/include/
X11/ICE/ICElib.h 及び X11R7.7/lib/libICE-1.0.8/src/connect.c では、関数名は IceGetConnectionContext
である。)
全ての ICE メッセージには、8 バイトの標準ヘッダがある。メッセージの読み書きを行う ICElib のマクロは、以下に掲げる命名規則に則って、メッセージ・ヘッダを解釈する。
CARD8 major_opcode; CARD8 minor_opcode; CARD8 data[2]; CARD32 length B32;
メッセージ・ヘッダの三番目と四番目のバイト(訳註:上記の data[2])は、必要に応じて使用する。length 欄の値は 8 バイト単位で記す。
ICE ライブラリは、メッセージの生成に用いる出力バッファ(output buffer)を保持している。ICE を基層とするプロトコルのライブラリでは、メッセージ群をまとめて一括処理することや、出力バッファを適宜放流する(flush)ことが可能である。
ICE 接続において入出力エラーが発生した場合、以後の全ての書込み操作は無視される。更なる情報は、エラー処理を見よ。
ICE 出力バッファの容量を知るには、IceGetOutBufSize
を用いる。
ice_conn |
有効な ICE 接続オブジェクト。 |
ICE 出力バッファを放流する(flush)には、IceFlush
を用いる。
ice_conn |
有効な ICE 接続オブジェクト。 |
出力バッファは、メッセージの生成に不十分な空き領域しかない場合、暗々裏に放流されることがあるので注意する。
以下のマクロは ICE メッセージの生成に使用できる。
IceGetHeader(
IceConn ice_conn, int major_opcode, int minor_opcode, int header_size, <C_data_type> *pmsg)
;
ice_conn |
有効な ICE 接続オブジェクト。 |
major_opcode |
メッセージの主命令コード。 |
minor_opcode |
メッセージの従命令コード。 |
header_size |
メッセージ・ヘッダの大きさ(バイト単位)。 |
<C_data_type> |
C 言語における、メッセージ・ヘッダの実際のデータ型。 |
pmsg |
メッセージ・ヘッダの領域を指すポインタ。 このマクロの呼出しの後、ライブラリはメッセージ・ヘッダ中にデータを格納できるようになる。 |
IceGetHeader
を用いて、引数で指定した ICE
接続におけるメッセージ・ヘッダを準備する。この準備作業では、メッセージ(*pmsg)の主・従命令コードを設定し、メッセージ長を表す(*pmsg
の) length 欄をヘッダ長と同じ値に合わせる。この後ろに可変長のデータが続く場合は、メッセージの length 欄を更新するものとする。
IceGetHeaderExtra(
IceConn ice_conn, int major_opcode, int minor_opcode, int header_size, int extra, <C_data_type> *pmsg, char *pdata)
;
ice_conn |
有効な ICE 接続オブジェクト。 |
major_opcode |
メッセージの主命令コード。 |
minor_opcode |
メッセージの従命令コード。 |
header_size |
メッセージ・ヘッダの大きさ(バイト単位)。 |
extra |
ヘッダ部分を除いた、後続データの大きさ(バイト単位)。 |
<C_data_type> |
C 言語における、メッセージ・ヘッダの実際のデータ型。 |
pmsg |
メッセージ・ヘッダの領域を指すポインタ。 このマクロの呼出しの後、ライブラリはメッセージ・ヘッダ中にデータを格納できるようになる。 |
pdata |
メッセージ・ヘッダの領域の直後に位置する ICE 出力バッファへのポインタが返る。可変長データはここに格納される。ICE 出力バッファに十分な空き領域がなかった場合、pdata は NULL に設定される。 |
IceGetHeaderExtra
を用いて、大きさの確定した(比較的小さな)可変長データを伴うメッセージを生成する。このメッセージの全身(complete message)は ICE 出力バッファに納まらなければならない。
ice_conn |
有効な ICE 接続オブジェクト。 |
major_opcode |
メッセージの主命令コード。 |
minor_opcode |
メッセージの従命令コード。 |
IceSimpleMessage
を用いて、ICE ヘッダ・メッセージと同じ大きさの、且つそれ以上の後続データを持たないメッセージを生成する。
IceErrorHeader(
IceConn ice_conn, int offending_major_opcode, int offending_minor_opcode, int offending_sequence_num, int severity, int error_class, int data_length)
;
ice_conn |
有効な ICE 接続オブジェクト。 |
offending_major_opcode |
エラーが検出されたプロトコルの主命令コード。 |
offending_minor_opcode |
エラーが検出されたプロトコルにおける従命令コード。 |
offending_sequence_num |
エラーを起こしたメッセージの通し番号。 |
severity |
|
error_class |
エラー・クラス(error class)。 |
data_length |
ヘッダに続く領域に書き込まれるデータの長さ(8 バイト単位)。 |
IceErrorHeader
によって、エラー・メッセージのヘッダを準備する。
ICE で接続された二者のクライアントが、同一のプロトコルに対して相異なる主命令コードを用いている可能性のあることに注意する。上記マクロに渡す offending_major_opcode は、エラー・メッセージを送信した方のクライアントに割り当てられた主命令コードである。
全てのプロトコルに共通の一般エラー(generic errors)には、0x8000~0xFFFF の範囲の値で表されるクラス(class)がある。詳細は規格文書 Inter-Client Exchange Protocol を見よ。
IceBadMinor | 0x8000 |
IceBadState | 0x8001 |
IceBadLength | 0x8002 |
IceBadValue | 0x8003 |
プロトコル毎のエラーのクラスは、0x0000~0x7fff の範囲で表す。
ICE 接続にデータを書き込むには、マクロ IceWriteData
を用いる。データが ICE 出力バッファに収まる時は、そこにデータを転写する。そうでない時は、ICE 出力バッファを放流した上で、直接データを送信する。
このマクロは IceGetHeader
及び IceErrorHeader
と組み合わせて使用する。
ice_conn |
有効な ICE 接続オブジェクト。 |
bytes |
書き込むデータのバイト数。 |
data |
書き込むデータ。 |
データを 16 ビット単位で書き込むには、IceWriteData16
を用いる。
ice_conn |
有効な ICE 接続オブジェクト。 |
bytes |
書き込むデータのバイト数。 |
data |
書き込むデータ。 |
データを 32 ビット単位で書き込むには、IceWriteData32
を用いる。
ice_conn |
有効な ICE 接続オブジェクト。 |
bytes |
書き込むデータのバイト数。 |
data |
書き込むデータ。 |
ICE 出力バッファへの転写作業を省くには、IceSendData
を用い、ネットワーク接続を通じて直接データを送信する。この際、必要であれば、まず ICE 出力バッファが放流される。
ice_conn |
有効な ICE 接続オブジェクト。 |
bytes |
送信するデータのバイト数。 |
data |
送信するデータ。 |
32 ビットもしくは 64 ビットの境界に揃えるには、IceWritePad
を用いる。詰め物は最大で 7 バイトまで指定できる。
ice_conn |
有効な ICE 接続オブジェクト。 |
bytes |
書き込む詰め物のバイト数。 |
ICE ライブラリは、メッセージの読み込みに用いる入力バッファを保持している。ICE ライブラリが、入力待機せずに適宜読み込みを行う様に実装された場合(nonblocking reads)、読み込み作業の度に 0 個以上のメッセージの全身(complete message)が入力バッファに読み込まれる。結果として、この節で説明する、メッセージ読み込みを行うマクロの全てについて、次のことが言える。即 ち、引数で指定された接続において実際の読み込み作業が行われるのは、入力バッファ中にデータが既に存在しない時に限られる。
ICE 入力バッファの容量を知るには、IceGetInBufSize
を用いる。
ice_conn |
有効な ICE 接続オブジェクト。 |
メッセージを読み込む時は、入出力エラーの有無を確認するよう気をつけなければならない。読込みの際に、メッセー
ジ中の何処かで何らかの入出力エラーが発生した場合、そのメッセージは捨てるものとする。以下で説明するマクロの何れかを用いてメッセージを読み込んだ後
には、マクロ IceValidIO
を用いて、接続上で入出力エラーが発生したか否かを調べることができる。ある ICE 接続において入出力エラーが発生してしまった後は、全ての読み込み操作は無視される。更なる情報は、エラーの処理を見よ。
ice_conn |
有効な ICE 接続オブジェクト。 |
以下のマクロを用いて ICE メッセージを読み込むことができる。
ice_conn |
有効な ICE 接続オブジェクト。 |
<C_data_type> |
C 言語における、メッセージ・ヘッダの実際のデータ型。 |
pmsg |
このポインタはメッセージ・ヘッダに合わせられる。 |
IceReadSimpleMessage
を用いて、次のようなメッセージを処理する。即ち、大きさが ICE ヘッダと同じ 8 バイトであり、且つヘッダ中の予備の 2
バイトを使って付加データを保持しているメッセージを処理する。ICE ライブラリは、メッセージの主命令コードを得るために、常にこの最初の 8
バイトを読み込む、という点に注意する。IceReadSimpleMessage
は、単にこの 8 バイトへのポインタを返すだけであり、実際には如何なるデータも入力バッファに読み込まない。
可変長データを伴うメッセージの読込みには、二通りのやり方がある。一つは、IceReadCompleteMessage
を用いて、メッセージの全身を一度に読み込む方法である。もう一つは、先にメッセージ・ヘッダを読み込み(ICE ヘッダの 8 バイトより大きいこともある)、次いで可変長データ部分を適度に区切って読み込む方法である。後者については、IceReadMessageHeader
と IceReadData
を見よ。
ice_conn |
有効な ICE 接続オブジェクト。 |
header_size |
メッセージ・ヘッダの大きさ(バイト単位)。 |
<C_data_type> |
C 言語における、メッセージ・ヘッダの実際のデータ型。 |
pmsg |
このポインタはメッセージ・ヘッダに合わせられる。 |
pdata |
このポインタはメッセージの可変長データ部分に合わせられる。 |
ICE 入力バッファに十分な空きがあれば、IceReadCompleteMessage
はメッセージの全身を ICE
入力バッファに読み込む。空きがなければ、可変長データ部分を容れるバッファを新たに確保する。このマクロの呼出しの後、引数 pdata を NULL
と比べて、バッファを確保するのに十分なメモリが存在したことを確かめるものとする。
IceReadCompleteMessage
を呼び出してメッセージを処理した後には、IceDisposeCompleteMessage
を呼び出すものとする。
ice_conn |
有効な ICE 接続オブジェクト。 |
pdata |
|
可変長データを容れるためにバッファを確保しなければならなかった場合(ICE 入力バッファに収まらなかったが故に)、そのバッファはこのマクロを通じて、ICElib の手で解放される。
ice_conn |
有効な ICE 接続オブジェクト。 |
header_size |
メッセージ・ヘッダの大きさ(バイト単位)。 |
<C_data_type> |
C 言語における、メッセージ・ヘッダの実際のデータ型。 |
pmsg |
このポインタはメッセージ・ヘッダに合わせられる。 |
IceReadMessageHeader
は、メッセージのヘッダだけを読み込む。残りのデータは、IceReadData
系のマクロで読み込むことになる。このメッセージ読込みの手法は、可変長データ部分を適度に区切って読み込まなければならない時に採用する。
利用者が用意したバッファに直接データを読み込むには、IceReadData
を用いる。
ice_conn |
有効な ICE 接続オブジェクト。 |
bytes |
読み込むバイト数。 |
pdata |
利用者が用意した当バッファにデータが読み込まれる。 |
データを 16 ビット単位で読み込むには、IceReadData16
を用いる。(訳註:X11R7.7/lib/libICE-1.0.8 では未実装。引数 swap を無視して IceReadData と同じ作業を実行している。)
ice_conn |
有効な ICE 接続オブジェクト。 |
swap |
|
bytes |
読み込むバイト数。 |
pdata |
利用者が用意した当バッファにデータが読み込まれる。 |
データを 32 ビット単位で読み込むには、IceReadData32
を用いる。(訳註:X11R7.7/lib/libICE-1.0.8 では未実装。引数 swap を無視して IceReadData と同じ作業を実行している。)
ice_conn |
有効な ICE 接続オブジェクト。 |
swap |
|
bytes |
読み込むバイト数。 |
pdata |
利用者が用意した当バッファにデータが読み込まれる。 |
32 ビットもしくは 64 ビットの境界に揃えるには、IceReadPad
を用いる。詰め物は最大で 7 バイトまで指定できる。
ice_conn |
有効な ICE 接続オブジェクト。 |
bytes |
詰め物のバイト数。 |
ICElib には標準のエラー・ハンドラ(処理器)が二つある。
一つは、主に致命的な事態(fatal conditions)を扱う(例えば、機器の故障で接続が絶えた等)。
一つは、ICE 固有のプロトコル・エラーを扱う。
もし独自のエラー処理手続きを設定したいのであれば、上の二つのエラー・ハンドラは、利用者の用意した手続きと取り替えることができる。この取替えは何度でも可能である。
ICE エラー・ハンドラを設定するには、IceSetErrorHandler
を用いる。
handler |
ICE エラー・ハンドラ。標準のハンドラに戻すには、NULL を渡す。 |
IceSetErrorHandler
は、この時まで使用されていたエラー・ハンドラを返す。
ICE エラー・ハンドラは、予期せぬ ICE プロトコル・エラー(主命令コード 0)が発生した時に呼び出される。標準搭載のハンドラの動作は、説明的な文を stderr
に表示し、重症度が「致命的(fatal)」であれば、0 でない値を付して exit
を呼び出す、というものである。exit
で終了してしまうのが望ましくない場合、アプリケーション側で独自のエラー・ハンドラを登録する。
他のプロトコルの法域で起こるエラーは、それぞれのプロトコル・ライブラリで処理することに注意する(各ライブラリに独自のエラー・ハンドラ備えるものとする)。
ICE エラー・ハンドラの関数型は IceErrorHandler
である。
typedef void (*IceErrorHandler)(
IceConn ice_conn, Bool swap, int offending_minor_opcode, unsigned long offending_sequence_num, int error_class, int severity, IcePointer values)
;
ice_conn |
ICE 接続オブジェクト。 |
swap |
値(the values)のバイト順交換が必要か否かを示す印。 |
offending_minor_opcode |
違反したメッセージの ICE 従命令コード。 |
offending_sequence_num |
違反したメッセージの通し番号。 |
error_class |
違反したメッセージのエラー・クラス。 |
severity |
|
values |
指定された従命令コードとクラス次第で必要となるエラー値。 |
ICE の層では、以下のエラー・クラスが定義されている。
IceBadMinor
IceBadState
IceBadLength
IceBadValue
IceBadMajor
IceNoAuth
IceNoVersion
IceSetupFailed
IceAuthRejected
IceAuthFailed
IceProtocolDuplicate
IceMajorOpcodeDuplicate
IceUnknownProtocol
詳しくは Inter-Client Exchange Protocol を見よ。
致命的な入出力エラーを処理するために、IceSetIOErrorHandler
を用いる。
handler |
入出力エラーのハンドラ(処理器)。標準のハンドラに戻すには、NULL を渡す。 |
IceSetIOErrorHandler
は、この時まで使用されていた入出力エラー・ハンドラを返す。
ICE 入出力エラー・ハンドラの関数型は、IceIOErrorHandler
である。
ice_conn |
ICE 接続オブジェクト。 |
ICElib で入出力エラーを処理するには、二通りのやり方がある。
一つ目は、入出力エラーの処理に必要な全ての作業を入出力エラー・ハンドラに行わせ、さりながら、そのエラー・ハンドラ中では IceCloseConnection
を呼び出さずに、同ハンドラから復帰するやり方である。この時 ICE 接続は「bad IO」状態となり、同接続に対する以後の読み書き全てが無視される。次回 IceProcessMessages
が呼び出された時、IceProcessMessagesIOError
という状態が返ってくる。その時になって、アプリケーションから IceCloseConnection
を呼び出す。
二つ目は、入出力エラー・ハンドラの中で IceCloseConnection
を呼び出し、次いで longjmp
命令を用いてアプリケーションのメイン・イベント・ループに戻るやり方である。setjmp
命令と longjmp
命令は全ての環境で適切に機能するとは限らない。特にメモリ漏れ(memory leaks)が起こらないように注意しなければならない。したがって、この二つ目の方式は、一つ目のものに比べて好ましくない。
入出力エラーの通知を受け取るように設定されているプロトコル・ライブラリでは、アプリケーションの入出力エラー・ハンドラが呼び出される前に、独自の IceIOErrorProc
型ハンドラが呼び出される。このハンドラは、プロトコル登録関数にて設定され(IceRegisterForProtocolSetup
及び IceRegisterForProtocolReply
を見よ)、そのプロトコルだけに関わる異状の始末をつける。
ice_conn |
ICE 接続オブジェクト。 |
全ての IceIOErrorProc
型コールバックは必ず返って来なければならない(must return)ということに注意する。これは、有効なプロトコルの各々が接続破断の通知を必要としているためである。アプリケーションの入出力エラー・ハンドラは、その後に呼び出されなければならない。
アプリケーションにて複数のスレッドが ICE ライブラリを使用することを宣言するには、IceInitThreads
を用いる。
マルチ・スレッドを利用するプログラムで最初に呼び出される ICElib 関数は、IceInitThreads
でなければならない。この関数の呼出しは、他の ICElib 呼出しが行われる前に完了しなければならない。IceInitThreads
が 0 でない Status を返すのは、この関数でスレッド・パッケージ(threads package)の初期化に成功した時であり、且つその時に限られる。IceInitThreads
を複数回呼び出しても問題はない。そのようにしても、スレッド・パッケージ(threads package)は一度しか初期化されない。
ICElib を基層とするプロトコル・ライブラリでは、ICE 接続とやり取りする、コード中の急所部分(critical sections)に排他錠を掛けなければならない(例えば、メッセージを生成する時)。大抵はマクロとして実装される関数を二つ用意している。
ice_conn |
ICE 接続オブジェクト。 |
複数回の ICElib の呼出しを跨いで ICE 接続の排他錠を維持するには、アプリケーションにて IceAppLockConn
及び IceAppUnlockConn
を用いる。
ice_conn |
ICE 接続オブジェクト。 |
関数 IceAppLockConn
は、IceAppUnlockConn
が呼び出されるまでの間、引数で指定された接続から他のスレッド群を完全に閉め出す。同接続に対して ICElib 関数を呼び出そうとする他のスレッド群は待機させられる(block)。プログラム中で前以って IceInitThreads
を呼び出していない場合、IceAppLockConn
は何もしない。
ice_conn |
ICE 接続オブジェクト。 |
IceAppLockConn
を呼び出したスレッドが関数 IceAppUnlockConn
を呼び出すことで、前者の関数のために待機させられていた他のスレッド群は、操作対象となった接続に対する ICElib 関数の呼出しを完遂できるようになる。プログラム中で前以って IceInitThreads
を呼び出していない場合、IceAppUnlockConn
は何もしない。
一時的な作業領域(scratch space)を確保するには(例えば可変長データ付きのメッセージを生成する時)、IceAllocScratch
を用いる。各 ICE 接続には、この一時作業領域が一つづつ備わっている。一時作業領域は空の状態から始まり、必要に応じて増えていく。何らかの ICElib 関数が呼び出された後には、一時作業領域の中身が保たれている保証はない。
ice_conn |
ICE 接続オブジェクト。 |
size |
要求するバイト数。 |
IceAllocScratch
の戻り値として取得した記憶領域は、同関数の呼出者が解放してはいけないという点に注意する。この領域は、領域を保持する ICE 接続が閉じられた時に、ICE ライブラリによって解放される。
ICE ライブラリの設計は、Bob Scheifler 氏の助言に負うところが大きいので、ここでお礼を申し上げる。また、Jordan Brown 氏、Larry Cable 氏、Donna Converse 氏、Clive Feather 氏、Stephen Gildea 氏、Vania Joloboff 氏、Kaleb Keithley 氏、Stuart Marks 氏、Hiro Miyamoto 氏、Ralph Swick 氏、Jim VanGilder 氏、及び Mike Wexler 氏にもお礼を申し上げる。
本文書で既に述べたように、ICE ライブラリが認証データ(ConnectionSetup
メッセージや ProtocolSetup
メッセージで使用するもの)を取得する方法は、実装によって異なる。†[2]
この附録では、ICE 許認可ファイル(ICE authority file)を操作する用役関数(utility functions)について説明する。許認可ファイルは、クライアント間での認証データの受け渡しに用いることができる。
.ICEauthority ファイルに対する基本的な操作としては、以下のものがある。
ファイル名を取得する
排他錠を掛ける
排他錠を外す
項目(entry)を読み込む
項目(entry)を書き込む
項目(entry)を検索する
これらは比較的低水準な操作であり、ファイル中の項目を加え、削り、表示する「iceauth」のような名前のプログラムが存在することを想定している。
これらの用役関数を用いるには、ヘッダ・ファイル <X11/ICE/ICEutil.h> を取り込まなければならない(include)。
.ICEauthority ファイル中の項目(entry)一つは、次のデータ構造を以って定義されている。
typedef struct { char *protocol_name; unsigned short protocol_data_length; char *protocol_data; char *network_id; char *auth_name; unsigned short auth_data_length; char *auth_data; } IceAuthFileEntry;
protocol_name 部には、接続設定時の認証であれば「ICE」が、そうでなければ下位プロトコルの名前(例えば「XSMP」)が入る。それぞれの項目(entry)におい て、protocol_data 部にプロトコル固有のデータを記載することができる。このデータは、ファイルから削除する必要のある古い項目を探すのに役立つ。
network_id 部には、認証を受理する側のクライアントのネットワーク ID が入る(例えばセッション・マネージャのネットワーク ID)。ネットワーク ID は次の書式で表される。
tcp/<hostname>:<portnumber> | もしくは |
decnet/<hostname>::<objname> | もしくは |
local/<hostname>:<path> |
auth_name 部には認証方式の名前が入る。auth_data 部には実際の認証データが入り、auth_data_length 部にはそのデータのバイト数が入る。
標準の許認可ファイル名を取得するには、IceAuthFileName
を用いる。
環境変数 ICEAUTHORITY が設定されていれば、その値が返る。さもなければ、$HOME/.ICEauthority が標準の許認可ファイル名となる。この名前を保持する領域は静的に割り当てられているので、解放してはいけない。
同期をとって許認可ファイルを更新するには、IceLockAuthFile
を呼び出してファイルに排他錠を掛けなければならない。この関数はシステム・コール link
の仕組みを利用している。即ち、新しいリンクの名前が既に存在するものと被った場合に、link
の呼出しが蹉跌するという現象を利用している。
file_name |
排他錠を掛ける許認可ファイル。 |
retries |
再試行の回数。 |
timeout |
再試行と再試行との間の秒数。 |
dead |
dead で指定された秒数を超えて存続している排他錠が既にあれば、これを破棄する。無条件に先行の排他錠を破棄するには、dead に 0 を渡す。 |
下記の三つの値のうち一つが返る。
IceAuthLockSuccess
- 排他錠を掛けるのに成功した。
IceAuthLockError
- システム・エラーが発生。errno
の出番である。
IceAuthLockTimeout
- 指定された回数分の試行が全て失敗に終わった。
許認可ファイルに掛かった排他錠を外すには、IceUnlockAuthFile
を用いる。
file_name |
排他錠を外す許認可ファイル。 |
許認可ファイル中の次の項目(entry)を読み込むには、IceReadAuthFileEntry
を用いる。
auth_file |
許認可ファイル(authorization file)。 |
この関数を呼び出す前に、読み込むべきファイルを開いておくのは、アプリケーションの仕事である。エラーが起きるか、読み込むべき項目(entry)がなくなれば、NULL が返る。
取得した項目(entries)は IceFreeAuthFileEntry
を呼び出して解放するものとする。
許認可ファイル中に項目(entry)を一つ書き込むには、IceWriteAuthFileEntry
を用いる。
auth_file |
許認可ファイル(authorization file)。 |
entry |
書き込む項目(entry)。 |
この関数を呼び出す前に、書き込むべきファイルを開いておくのは、アプリケーションの仕事である。関数が成功裡に終われば、0 でない Status が返る。
標準(default)の許認可ファイルの中から、指定された protocol_name/network_id/auth_name の組に一致する項目を探し出すには、IceGetAuthFileEntry
を用いる。
IceAuthFileEntry *IceGetAuthFileEntry(
const char *protocol_name, const char *network_id, const char *auth_name)
;
protocol_name |
項目検索に用いるプロトコル名。 |
network_id |
項目検索に用いるネットワーク ID。 |
auth_name |
項目検索に用いる認証方式名。 |
IceGetAuthFileEntry
の結果、指定したような項目が見つからなかった場合、NULL が返る。
IceReadAuthFileEntry
もしくは IceGetAuthFileEntry
で取得した項目(entry)を解放するには、IceFreeAuthFileEntry
を用いる。
entry |
解放する項目(entry)。 |
X 協会の ICElib の実装には、MIT-MAGIC-COOKIE-1 を利用した簡易な認証機構が備わっている。この機構は附録 A で述べた、許認可ファイル利用関数を用いている。
この方式において、セッションマネージャのような位地にあるアプリケーションは、まず IceGenerateMagicCookie
を呼び出してマジック・クッキーを取得し、次いで利用者の手元の(local) .ICEauthority
ファイル中にそのマジック・クッキーを記録する。これによって、ローカル(訳註:local <-> remote)のクライアントは先のアプリケーションに接続できるようになる。遠隔の
クライアントが接続できるようにするには、遠隔機上にある利用者の .ICEauthority
ファイル中にマジック・クッキーを記録するための、何らかの遠隔実行の仕組みを用いる。
アプリケーションでは、「.ICEauthority」ファイルにマジック・クッキーを書き込むに止まらず、同クッキーをメモリにも書き込むため、関数 IceSetPaAuthData
を呼び出す必要がある。MIT-MAGIC-COOKIE-1 認証手続きにおいて接続を受理・拒否する段になると、同手続きでは、申請者(requestor)の提示するマジック・クッキーとメモリにあるマジック・クッキーとの比較が行われる。
length |
マジック・クッキーの長さを指定。 |
戻り値たるマジック・クッキーは null 文字終端である。マジック・クッキーのためにメモリ(一時記憶領域)を割り当てられなかった時は、上の関数は NULL を返す。さもなければ、取得したマジック・クッキーは free
を呼び出して解放する。
認証データを一時記憶領域(memory)に写すには、IceSetPaAuthData
を用いる。この関数は、今のところ MIT-MAGIC-COOKIE-1を用いた認証にしか使用されていないが、将来は他の認証方式で利用されることもあろう。
num_entries |
認証データの項目(entry)数。 |
entries |
認証データの項目(entry)の配列(訳註:将来、連結リストにしたいらしい)。 |
各項目(entry)には、プロトコルの名前(例えば、ICE 接続設定の認証であれば「ICE」、セッション管理の認証であれば「XSMP」)、受理方クライアントのネットワーク ID、認証方式の名前(例えば MIT-MAGIC-COOKIE-1)、そして認証データが結び付けられている。ICE ライブラリでは、渡された項目群と前から設定されていた項目群とを、「protocol_name、network_id、auth_name」の三値一 組を鍵として、混ぜ合わせる(merge)。(訳註:libICE-1.0.8/src/setauth.c では、三値同一の項目があれば、新しく渡された項目で上書きする。その他の新項目は配列の後ろに足していく。)
typedef struct { char *protocol_name; char *network_id; char *auth_name; unsigned short auth_data_length; char *auth_data; } IceAuthDataEntry;