MMMM
平成29年1月27日(金)
「An ICE Rendezvous Mechanism for X Window System Clients(日本語訳)」
A Remote Access Protocol for the X Window System の参考文献欄によると「Unpublished report, Disability Action Committee for X, 1994.」のようだが、違うかもしれない。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++

X ウィンドウ・システム・クライアントの ICE ランデヴ機構

William D. Walker 著

要旨

 ICE は、クライアント間の接続を確立するための便利な仕組みである。しかしながら、ICE で通信し合うクライアントの双方にとって、相手の存在を認識し、その上で相手との ICE 接続を開始する、という動作は難しい。本文書では、この開始方法の問題を取り上げる。そして、X ウィンドウ・システムのクライアントが通信開始の前段階で利用することになる ICE ランデヴ機構について論じ、同機構の作成方法として三つの選択肢を検討する。

謝辞

 Sue Liebeskind、Keith Edwards、Beth Mynatt、Donna Converse、Ralph Swick、Daniel Dardailler、Ralph Mor、Anselm Baird-Smith、そして Dave Hill、彼らの発想、設計に纏わる見識、X ウィンドウ・システムの知識に感謝する。また、X のスクリーン・リーダという、始原の課題を生み出してくれた DACX(Disability Action Committee for X) にも感謝する。

定義

 本文書を通して、クライアント、エージェントという用語は以下の定義に遵う。

クライアント
 X ウィンドウ・システムの標準的なクライアントのこと。

 クライアントの例を挙げると、文章を書くアプリケーション、ウィンドウ・マネージャ、ターミナル・アプリケーションなどである。

エージェント
 X ウィンドウ・システムのクライアントであり、自分以外のクライアントに関心を持つ特別な者のこと。

 エージェントの例を挙げると、リソース・エディタ、音声フィードバック・クライアント、スクリーン・リーダ、及びテスト・ツールである。

全体像

  DACX は X ウィンドウ・システムが目の見えない人にも一層扱い易いものになるよう改良していく取組みであったが、この取組みの結果として、RAP(Remote Access Protocol)が誕生した。X ウィンドウシステムのクライアントと通信し、相手クライアントのユーザ・インタフェイスの状態を把握し、そのインタフェイスの状態を何とか操作する。このような動作をエージェントがとれるようにするのが RAP の真の狙いである。

 RAP を可能にする技術は、大きく三つに分けられる。

 第一の要素即ちランデヴ機構が本文書の主題である。X11R6 から導入された ICE プロトコル[1]によって、上記第二の要素に必要なクライアント間通信の仕組みが齎された。同じく X11R6 から加わった Xt フック[6]によって、上記第三の要素の半分が用意された。Xt フックは Xt クライアントが使用する。そして、第三の要素のあと半分は RAP プロトコルそのものであり、別の文書でこれを扱う。

要件

 先の節で述べたように(訳註?)、RAP の要は「意識されない」ランデヴ機構であり、エージェントとクライアントはこれを用いて自動的に相互の通信を確立する。ランデヴ機構の要件は次の通り。

  1. ランデヴ機構は、クライアント側にソースコードの修正を求めてはならない。但し、既存のクライアントの再連繋(re-link)を求めるのは良い。
  2. ランデヴ機構は、軽量であるべきであり、クライアントの実行速度に響くのは避けるべき。
  3. ランデヴ機構は、クライアントが動き出してから、出来る限り速い段階で使われ始めるべき。
  4. クライアントは、同時に複数のエージェントと通信できなければならない。たとえ、そのエージェントの中の複数が同一のプロトコルを使用しているとしても。
  5. クライアントとエージェントは、任意の順に起動・終了できる。
  6. クライアントが同時にエージェントであっても良い。

 第一の要件を満たすことによって、既存のアプリケーションを RAP 及び RAP 系セッションに参加させることが出来るようになる。加えて、この要件によって、アプリケーション開発者が RAP 系プロトコルに対応したものを作る必要もなくなる。

 第二の要件は、RAP 系セッションへの参加を望まないクライアントの話であり、こうしたクライアントが使いもしない機能によって実行速度の低下を強いられないようにするためのものである。

 試験アプリケーションやユーザ・インタフェイス看視ツールでは、クライアントのユーザ・インタフェイスについての情報を出来る限り早い段階で、ことによってはディスプレイ接続を開いた段階で取得したいということもあるかもしれない。第三の要件は、この種のアプリケーションの需要を満たすために設定したものである。

 第四の要件によって、複数のエージェントが同一のクライアントと同時に通信できるようになる。例えば、エージェントを使ってクライアントの試験をしている盲目の利用者は、さらにスクリーン・リーダ[7]を用いて同クライアントに接続することもできる。

 第五の要件によって、クライアントとエージェントは好きな時に起動・終了することができるようになる。結果として、セッション・マネジメント・プロトコル[3]でも話題になる「こちらが先に存在していなければならない」という状況を考えなくて済む。

 最後の要件によって、エージェントはクライアントとしても振舞うことが出来るようになる。これは第四の要件とも係わってくる。例えば、エージェントで動作試験を行っている目の見えない利用者は、そのエージェントの操作にあたって、スクリーン読み取りエージェントを使うことができる。

ICE の概要

 ICE プロトコルによって、X から独立した形の「クライアント間」通信が可能になる。この通信は、Editres プロトコルで用いている ClientMessage / Selection 機構よりもかなり速い。アプリケーション A とアプリケーション B との間に ICE 接続を確立する手続きは以下の通り。

  1. ICE を基層とする何らかのプロトコルの開始要求に備えて、アプリケーション A は ICE のプロトコル・リプライの用意をする。そこでアプリケーション A は IceListenForConnections リクエストを ICE に送り、割り当てられた ICE ネットワーク ID の一群を受け取る。ICE ネットワーク ID の概念は X Display ID のそれに似ている。アプリケーション A への接続を図るアプリケーションは、前もって ICE ネットワーク ID を知らなければならない。
  2. ICE を基層とする何らかのプロトコルの開始要求を行うべく、アプリケーション B は ICE のプロトコル・セットアップの用意をする。本文書で述べるランデヴ機構などを利用してアプリケーション B がアプリケーション A の存在を認識すると、アプリケーション B は A のネットワーク ID を用いて IceOpenConnection リクエストを発し、アプリケーション A との接続を開始する。一度 ICE 接続が開設された後は、アプリケーション B は IceProtocolSetup リクエストを発し、どのプロトコルに則って通信したいのかをアプリケーション A に通知する。

 ICE に則った通信を確立するにあたっての最大の障碍は、アプリケーション B に次の二つの情報を教えることである。一つはアプリケーション A の ICE ネットワーク ID であり、もう一つはアプリケーション A がアプリケーション B と同じプロトコルを使って通信できるか否かである。この二つの情報は、アプリケーション A との ICE 接続を開始するために必要不可欠のものである。本文書の残りの部分ではこの問題に焦点を当て、アプリケーション B に上の情報を齎すランデヴ機構について、その候補案を三つ検討する。

エージェントに ClientMessage イベントを使わせる

 ランデヴ機構の最初の候補では、エージェントが上記アプリケーション A に当たり、クライアントが上記アプリケーション B に当たる。起動時に、エージェントは、使用可能なプロトコル(複数可)を ICE に登録し、IceListenForConnections を実行し、その結果得られる ICE ネットワーク ID 群を自身の最上位ウィンドウのプロパティ ICE_NETWORK_IDS に保存する。

 次いでエージェントは、最上位のクライアント・ウィンドウ全てを見て、それらに対して ClientMessage イベントを送信する。この ClientMessage イベントには、エージェントの最上位ウィンドウの ID、通信で使いたいプロトコルの名前、プロパティ ICE_NETWORK_IDS を指すポインタが入る。さらにエージェントは、ディスプレイのルート・ウィンドウに SubstructureNotify イベントの登録をする。エージェントは SubstructureNotify イベントを受信すると、そのイベントの由来がクライアントの最上位ウィンドウの新規作成なのか否かを調べる。もしそうであれば、エージェントは、起動時に既存のクライアントへ送信したものと同じ ClientMessage イベントを件の新たなウィンドウにも送信する。

 起動時に、各クライアントは ClientMessage イベントの登録をする。このイベントを受けるハンドラは、そのメッセージがエージェントから来たのか否かを調べる。もしそうであれば、同クライアントは自身がそのエージェントと同じプロトコルを使って通信できるか否かを調べる。これが可能であれば、同クライアントは、エージェントのウィンドウにあるプロパティ ICE_NETWORK_IDS から ICE ネットワーク ID を取得し、ICE 接続を開始する。

 この仕組みの最大の利点は、如何なるエージェントが存在するのかを割り出すための名簿管理が不要な点である。加えて、クライアントの起動時に為すべき作業が ClientMessage イベントの回覧登録しかないというのも利点である。クライアントの動作期間中に起動したエージェントが皆無であれば、同クライアントは実行速度の低下と無縁でいられる。

 この方式の主な欠点は、ICE 接続の開始に先立って、エージェントとクライアントの双方がウィンドウの作成を済ませていなければならないことである。これでは遅いというエージェントもあるかもしれない。もっとも、ICE に基づく通信は、エージェントとクライアントの両者がイベントを処理する基幹ループに入るまでは本格的に実行することが出来ないという見方もあろう。もう一つこの方式の欠点を挙げれば、知らないイベントを受け取った時に exit() を呼び出してしまう行儀の悪いクライアントが存在することである。例えば、アプリケーション Editres の発する ClientMessage を受け取って停止してしまったアプリケーションが幾つかある。これはクライアント側のバグであるとも言えるが、出来れば避けるべきである。

クライアントの最上位ウィンドウで周知のプロパティを管理させる

 ランデヴ機構の二番目の候補は最初のものと似ているが、今度はクライアントがアプリケーション A に当たり、エージェントがアプリケーション B に当たる。この機構の場合、クライアントは自身の最上位ウィンドウに二つのプロパティを保持することになる。一つは ICE_NETWORK_IDS であり、もう一つは PROTO_NAMES である。

 起動の際、各クライアントは使用可能なプロトコル(複数可)を ICE に登録し、同時に同プロトコルの名前を自身の最上位ウィンドウのプロパティ PROTO_NAMES に記録する。さらに、クライアントは IceListenForConnections を実行し、その結果得られる ICE ネットワーク ID 群を自身の最上位ウィンドウのプロパティ ICE_NETWORK_IDS に書き留める。

 起動時に、各エージェントはディスプレイ全体の最上位ウィンドウを見て、PROTO_NAMES プロパティがないかどうか調べる。エージェントにも使えるプロトコルを挙げているウィンドウが見つかり、そのクライアントとの ICE 接続を開始すべきと思われた場合、エージェントは同プロトコルを ICE に登録し、クライアントの ICE_NETWORK_IDS プロパティを利用して同クライアントとの ICE 接続を開始する。先のランデヴ機構案と同様に、エージェントはディスプレイのルート・ウィンドウに SubstructureNotify イベントの回覧登録をする。エージェントに SubstructureNotify イベントが届くと、同エージェントは新たなウィンドウにプロパティ PROTO_NAMES があるのか無いのかを調べる。もし同プロパティが存在し、且つエージェントがそのプロトコルで通信可能ならば、エージェントはプロパティ ICE_NETWORK_IDS を取り寄せて、新しいクライアントとの接続を開始する。

 この仕組みが先の案に比べて優れているは、主に ClientMessage イベントを必要としない点である。この手法の主な欠点は、クライアントに ICE プロトコルの登録と、ICE 接続の待受けとを強いる点である。これらのプロトコルも接続も、全く活かされないかもしれないのである。クライアントはエージェントより数が多いので、このようなやり方では ICE ネットワーク ID が大量に無駄になってしまう。欠点はもう一つある。エージェントがルート・ウィンドウからの SubstructureNotify イベントを受け取る時までに、クライアントが自身の最上位ウィンドウへの PTORO_NAMES プロパティの書き込みを完了していないこともあり得る。そのため、無視されるクライアントが発生するかもしれない。

エージェントにルート・ウィンドウ上で周知のプロパティを管理させる

 ランデヴ機構の最後の候補では、エージェントがアプリケーション A に当たり、クライアントがアプリケーション B に当たる。仕組みの肝は、エージェントがディスプレイのルート・ウィンドウ上で周知のプロパティ EXT_AGENTS を管理することである。この周知済みプロパティは情報単位の配列であり、単位要素にはエージェントを表す一意の ID、エージェントの ICE ネットワーク ID 群、及びエージェントの使えるプロトコル群が含まれる。

 起動時に、各エージェントは使用できるプロトコルを ICE に登録し、IceListenForConnections を実行する。次いでエージェントは、返ってきた ICE ネットワーク ID 群とプロトコル名とをルート・ウィンドウのプロパティ EXT_AGENTS に書き加える。

 起動時に、各クライアントはルート・ウィンドウのプロパティ EXT_AGENTS を調べ、知ったプロトコルで通信できるエージェントがいるかどうかを確認する。そうしたエージェントが存在すれば、クライアントはそのプロトコルを ICE に登録し、同エージェントとの ICE 接続を開始する。これに加えて、クライアントはプロパティ EXT_AGENTS に関する PropertyNotify イベントの登録をしなければならない。このプロパティに変更があった時は、クライアントは通信できる新規エージェントがいるかどうかを確認し、結果次第で更なる ICE 接続を開始する。

 この方式の最大の利点は、エージェントとクライアントがかなり早い段階で合流できることである。XOpenDisplay とほぼ同時にランデヴを実現できる。また、EXT_AGENTS は共用の記録場所として別の目的にも役立てることが出来る。さらに、この機構案では、最初の候補が使っていた ClientMessage イベントは不要である。

 この方式の主な欠点は、周知のプロパティを保守するために帳簿管理作業が必要なことである。エージェントが思いがけず停止した場合、プロパティ EXT_AGENTS は現状を反映しなくなってしまう。この問題の解決するには、新しいエージェントとクライアント全てに EXT_AGENTS 内の目録を更新させ、存在しないエージェントを指す項を取り除く必要がある。クライアント側におけるプロパティ EXT_AGENTS の確認と更新の手間は最小限のものではあるが、クライアントの起動にかかる時間が増えることは間違いない。

 欠点はまだある。エージェントが自身をプロパティ EXT_AGENTS に追加・削除する度に、全てのクライアントが PropertyNotify イベントを受信する。これは個々のクライアントにとっては大した負荷ではないが、全てを合わせるとシステムの速度に害を与えることになろう。また、プロパティ EXT_AGENTS の値が変わる度に各エージェントがそれを確認・更新する場合、同プロパティに対する変更が無限に続いてしまうことも考えられる。

結論

 機構案の二番目のものは最初のものによく似ているが、ClientMessage イベントを不要にした代わりに、全クライアントに対して、使うか分らないプロトコルを ICE へ登録するよう義務づけてしまった(一度も来ないかもしれない ICE 接続の待受けも)。これ故に、第一案の機構は第二案の機構より好ましい。

 第三案の機構は、エージェントとクライアントがかなり早い段階で合流することを可能にする代わりに、クライアントに対して起動時にプロパティ EXT_AGENTS を確認し、場合によっては同プロパティを更新することを強いてしまう。しかしながら、EXT_AGENTS の目録数は比較的少なく、管理のための余計な処理も最小限で済むはず。

 ルート・ウィンドウのプロパティ EXT_AGENTS を保守しなければならないというランデヴ機構第三案の小さな欠点と、クライアントとエージェントが ICE 接続開始前に既にウィンドウを作成していなければならないという第一案のより大きな欠点とを比べると、私は、[[[私には何れが良いのかわからない。最後の案が良いやり方のように思えるが、プロパティ EXT_AGENTS の保守に若干の不安がある。どれが良いか考えのある方はいますか???]]]

参考文献

[1] Robert Scheifler, Jordan Brown. "Inter-Client Exchange (ICE) Protocol." Version 1.0. X Consortium Standard. Version 11, Release 6.
[2] Ralph Mor. "Inter-Client Exchange (ICE) Library." Version 1.0. X Consortium Standard. Version 11, Release 6.
[3] Mike Wexler. "X Session Management Protocol." X Consortium Standard. Version 11, Release 6.
[4] Ralph Mor. "X Session Management Library." Version 1.0. X Consortium Standard. Version 11, Release 6.
[5] James Gettys, Robert Scheifler. "Xlib -- C Language Interface." X Consortium Standard. Version 11, Release 6.
[6] Joel McCormack, Paul Asente, Ralph Swick. "X Toolkit Intrinsics -- C Language Interface." X Consortium Standard. Version 11, Release 6.
[7] Elizabeth Mynatt, Keith Edwards. "The Mercator Environment: A Nonvisual Interface to X Windows and Unix Workstations." Multimedia Computing Group, Georgia Institute of Technology.
[8] Anselm Baird-Smith, Philippe Kaplan. "The k-Edit System." Update 07/94. http://zenon.inria.fr:8003/koala/k-edit.html.
[9] Chris Peterson. "Editres -- A Graphical Resource Editor for Users and Programmers." The X Resource: A Practical Journal of the X Window System. Issue 0. Fall 1991.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MMMM