入り口に戻る

原文はこちら。翻訳にあたって、オープンソースグループ・ジャパンの MIT ライセンスの訳を参考にした。

# X Session Management Protocol(日本語訳)

## X Consortium Standard

### Mike Wexler

Kubota Pacific Computer, Inc

X Version 11, Release 7.7

Version 1.0

Copyright © 1992, 1993, 1994, 2002 The Open Group

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 Window System is a trademark of The Open Group.

(訳)

(本ソフトウェアおよび関連する文書のファイル（以下「ソフトウェア」）の複製を取得した全ての人物に対し、以下の条件に従うことを前提に、ソフトウェアを無制限に扱うことを無償で許可する。これには、ソフトウェアの複製を使用、複製、改変、結合、公開、頒布、再許諾、および/または販売する権利、およびソフトウェアを提供する人物に同様の行為を許可する権利が含まれるが、これらに限定されない。)

(上記の著作権表示および本許諾表示を、ソフトウェアの全ての複製または実質的な部分に記載するものとする。)

(ソフトウェアは「現状有姿」で提供され、明示的であるか黙示的であるかを問わず、いかなる種類の保証も行われない。ここでいう保証には、商品性、特定目的への適合性、および権利の非侵害性に関する保証も含まれるが、これらに限定されるものではない。THE X CONSORTIUM は、契約、不法行為、またはその他の行為であるかを問わず、ソフトウェアまたはソフトウェアの使用もしくはその他に取り扱いに起因または関連して生じるいかなる請求、損害賠償、その他の責任について、一切の責任を負わない。)

(X Consortium の名称は、この表示に記載されている場合を除き、X Consortium の事前の書面による承認を得ずに、宣伝であろうとその他の形であろうと、ソフトウェアの販売を促進するもの、またはソフトウェアの使用その他の扱いを奨励するものに使用してはならない。)

(X Window System は The Open Group の商標である。)

この文書に記すプロトコルは、セッション・マネージャ(session manager)によって複数のクライアント・アプリケーション群を管理する手続きを定めたものである。セッション・マネージャを使うことで、クライアントに自身の状態を保存させること、クライアントを停止すること、前回保存時の状態でクライアントを再開することが可能になる。本プロトコルは X.Org ICE プロトコルを基層としている。

## 第一章 謝辞

最初に、批評・提言を通じて支援してくれた ICCCM と Intrinsics の作業部会の方々全員にお礼を申し上げる。また、次の方々に特別の感謝を申し上げる。アルファベット順に、Jordan Brown氏、Ellis Cohen氏、Donna Converse氏、Vania Joloboff氏、Stuart Marks氏、Ralph Mor氏、そして Bob Scheifler氏。

## 第二章 定義と目標

X Session Management Protocol (XSMP) は、利用者がセッションを保存・復元する仕組みについて、標準規格を打ち立てるために考案された。セッション(session)とは、クライアントの集合であり、一つ一つのクライアントは独自の状態を持つ。セッションの管理はセッション・マネージャ(session manager)と呼ばれるネットワーク・サービスで行う。セッション・マネージャは利用者に成り代わってクライアントに命令を発する。この命令でクライアントに状態保存を促したり、クライアントを停止したりすることができる。クライアントは次のような形で自身の状態を保存する。即ち、後々クライアントを再起動することができ、かつ、まるで一度も停止されていなかったかのようにクライアントの処理を再開できる形で保存する。クライアントの「状態」には、編輯中のファイルの情報や、ファイル中の現在の書込み位置、未処理のデータ交換の開始点に関する情報等を含めることが可能である。クライアントを再起動する手段については、本プロトコルでは定めない。

本プロトコルでは都合上、セッション・マネージャのクライアント(client)を「セッション・マネージャに対する接続」と定義している。クライアントは大抵、単一の X Window System ディスプレイ(display) に接続されたアプリケーションプログラムを実行するプロセスであるが、必ずしもこのような形態を採らなければいけない訳ではない。複数の X ディスプレイに接続されたクライアントも、接続される X ディスプレイを持たないクライアントも存在する。

このプロトコルは X 協会(X Consortium)の ICE プロトコルを基層としており、接続管理と認証の処理は ICE プロトコルに則って行う。

## 第三章 プロトコルの概要

クライアントは XSMP に則って自身をセッション・マネージャに登録する。クライアントは起動時にセッション・マネージャへの接続を図り、動作している限り接続状態を保ち続ける。クライアントがセッションから外れる際には、接続を断つ前に適切なプロトコルメッセージを発する。何も知らせることなく接続が途切れた場合、企図せずクライアントが停止したものと見做される。

クライアントの状態保存は、クライアントの複数の実体(instantiation)を一つ一つ独立に管理し得るような形で行われる必要がある。本プロトコルでは、クライアントの複数の実体を区別するために、クライアント ID (client-ID、クライアント識別子)と呼ばれる一意的な値を導入している。。例えば、クライアントが特定の実体の状態を記録する際、そのファイル名の一部にこの識別子を含めても良い。また、クライアント ID はクライアントを再起動するための命令文(the RestartCommand)の中にも記録する。こうすることでクライアントは再開後も同じ識別子を保持できるようになる。状態情報のうちの小さなものには、その記録を RestartCommand に入れられるものもある。例えば、X11 クライアントは、RestartCommand 中に「-twoWindow」指定を記載することで、再起動時に二つのウィンドウを表示する形で立ち上げるよう指示することができる。

クライアントがセッション・マネージャのネットワークアドレスを知る方法はシステムによって異なる。POSIX システムでは環境変数 `SESSION_MANAGER` にネットワーク ID(ネットワーク識別子)を並べたものが入っている。各識別子は伝送方式(transport)の名前、スラッシュ、伝送方式特有のアドレスで構成されており、TCP/IP のアドレスなら次のようになる。

`tcp/``hostname``:``portnumber`

ここでの hostname は完全修飾ドメイン名である。Unix Domain アドレスの場合。

`local/``hostname``:``path`

DECnet アドレスの場合。

`decnet/``nodename``::``objname`

複数のネットワーク ID が存在する時は、コンマで区切って記載する。

### 玄論

XSMP プロトコルの伝送方式の部分に X を採用するべきか、それとも独自の伝送方式を用いるべきかで大いに議論があった。いくつかの理由を基に独自のプロトコルを使用するという結論に至った。第一に、セッション・マネージャでは X の接続を持たないプログラムも管理する必要があること。第二に、X プロトコルは汎用な伝送方式として利用するのに向いていないこと。第三に、セッションは複数のディスプレイに跨がり得ることがその理由である。

本プロトコルは接続を基礎にしている。何故かというと、セッション・マネージャから見て、クライアントの終了時点を確定する方法が他にないからである。

このようにプロトコルを定めることで、新たな欠点が生まれてしまうことに注意しなければならない。セッション・マネージャが終了した後もクライアントを走らせ続けることは可能であるが、それが標準的なやり方になることはないと思われる。通常、セッション・マネージャを起動したプログラムは、セッション・マネージャの終了時点(正常終了でも異常終了でも)でセッションも終わったものと見做すであろう。

これを回避するには、ある種のランデヴサーバを導入する必要がある。しかし、そうするとまた新しい欠点が生じてしまう。単純で信頼できるセッション・マネージャを作るという理想の下、誰でも使用できるランデヴサーバを用意しないことによって XSMP は簡潔を保っているのであるから。

クライアントが起動したプログラムを当のクライアントに管理させたいこともあるであろう。例えば、メールプログラムはメールの文章を編輯するためにテキストエディタを立ち上げる。このように振る舞うクライアントはセッション・マネージャそのものである。起動したクライアントから起動されたクライアントへ適切な接続情報が送られる(例、環境変数 `SESSION_MANAGER`)。但し、その接続情報は最上位のセッション・マネージャに対するものではなく、起動者自身への接続に関するものである。

どのクライアントにもプロパティの一群が紐付けられている。あるクライアントによって設定されたプロパティは他のクライアントからは見られない。このようなプロパティを使用してクライアントからセッション・マネージャへ、クライアントの現在の状態を通知する。クライアントが初めてセッション・マネージャに接続される時点では、まだいかなるプロパティも設定されていない。

## 第四章 データの型

XSMP のメッセージでは、数種のデータの型を用いる。セッション・マネージャとクライアントの双方とも、常に独自のバイト順序でメッセージを記述し、そのまま送信する。そのため、どちらの側でも受信したメッセージのバイト列を並び替える必要が生じ得る。バイト列を並び替える必要があるか否かは、ICE プロトコルに則った処理を通じて、実行時に判断される。

下表のデータ型の値が入るべき場所に不正な値が入れられた場合、メッセージの受け手から送り手に宛てて、エラーメッセージ「BadValue」を送信しなければならない。

Type Name | Description
--- | ---
BOOL | `False` もしくは `True`
INTERACT_STYLE | `None`、`Errors` もしくは `Any`
DIALOG_TYPE | `Error` もしくは `Normal`
SAVE_TYPE | `Global`、`Local` もしくは `Both`
CARD8 | 1バイトの符号無し整数
CARD16 | 2バイトの符号無し整数
CARD32 | 4バイトの符号無し整数
ARRAY8 | CARD8 の配列
LISTofARRAY8 | ARRAY8 の配列
PROPERTY | プロパティの名前(ARRAY8 が一つ)、型の名前、その型の値
LISTofPROPERTY | PROPERTY の配列

## 第五章 プロトコルの開始手続きとメッセージの形式

XSMP の手続きを始めるにあたって、クライアントはサーバに対して ICE の `ProtocolSetup` メッセージを送信する。XSMP のメッセージは全て、標準の ICE メッセージの形式に則っている。メッセージの主たる命令コード(major opcode)は、実行時、ICE の次元で決定され、XSMP に割り当てられる。交信するクライアントとセッション・マネージャの両者において、XSMP を示す主命令コードとして異なる値が割り当てられることもある。一度主命令コードの値が割り振られた後、交信当事者の双方は自身の発する XSMP メッセージ全てにおいて各々決まった値を使用することになる。メッセージの従たる命令コード(minor opcode)は、当のメッセージが XSMP のどのメッセージを伝えるものなのかを表す。

## 第六章 クライアント識別文字列

クライアント ID は ISO Latin 1 (ISO 8859-1) 形式で符号化された XPCS 文字から成る文字列である。null 文字は使わない。クライアント識別文字列は、`RegisterClient` メッセージと `RegisterClientReply` メッセージで使用する。

クライアント ID は、後述する要素を順に繋げたものから成る。要素を繋げる際、区切り文字は用いない。全ての要素が所定の長さになるよう、各要素文字列の左側を文字「`0`」で詰める。１0進数は「`0`」から「`9`」までの文字を使って表し、１6進数は「`0`」から「`9`」までの文字と「`A`」から「`F`」までの文字を使って表す。

- 版の番号。現在の版は文字「`1`」である。

- アドレスの型とアドレス。アドレスの型は次のうちの一つ。

  '`1`' 4バイトの IPv4 アドレス。１6進数8桁で表す。
  '`2`' 6バイトの DECNET アドレス。１6進数１2桁で表す。
  '`6`' １6バイトの IPv6 アドレス。１6進数32桁で表す。

  当のアドレスは、セッション・マネージャが実行されている装置のネットワークアドレスの中の一つになる(クライアントが動作している装置のアドレスではない)。例を挙げると、IP アドレス「198.112.45.11」は文字列「`QC6702D0B`」に変換される。

- 時刻印(time stamp)。１970年１月１日00:00:00 UTC を起点としたミリ秒単位の時刻を１3桁の１0進数で表したもの。

- プロセス ID (process-ID、プロセス識別子)の型とプロセス ID 。プロセス ID は次のもの。

  '`1`' POSIX のプロセス ID を１0桁の１0進数で表したもの。

  プロセス ID は、セッション・マネージャのプロセス ID であって、クライアントのそれではない。

- 通し番号(sequence number)。4桁の１0進数で表され、セッション・マネージャが識別子を作る度に壱増えていく。「Q9999」に達した後、「Q0000」に巻き戻る。

  ### 玄論

  一度クライアントにクライアント ID が割り当てられると、そのクライアントはこの識別子を永続的に使い続ける。クライアントが停止し、再起動しても、再び同じ識別子が当てられる。計算機から計算機へ、利用者から利用者へ、セッション・マネージャからセッション・マネージャへ、クライアントが同一性を保ち続ける限り、同一のクライアント ID を通用させられるのが望ましい。このことと、クライアント ID の永続性を合わせると、クライアント ID は地球全体(globally)で一意でなければならない、ということになる。上で述べたクライアント ID の構造から次のことが言える。即ち、いかなる利用者、いかなるセッション・マネージャ、いかなる計算機によって作り出されたクライアント ID も、他のクライアント ID とは被らないということである。(訳註：そうでもない？)

## 第七章 プロトコル

このプロトコルは、後述するように一連のメッセージから成り立っている。メッセージ一つ一つの型は ICE 従命令コードで指定する。クライアントからセッション・マネージャへ送られるメッセージなのか、それともセッション・マネージャからクライアントへ送られるのかはメッセージの型毎に決まっており、各メッセージの説明欄に正しい方向が記載されている。また、メッセージのそれぞれの型に対して、有効な返答と起こり得るエラーメッセージの一覧が纏めてある。各エラー型に続く括弧の中に ICE の重症度が記されている。

    RegisterClient [Client → SM]

      previous-ID: ARRAY8

      Valid Responses: RegisterClientReply

      Possible Errors: BadValue (CanContinue)

クライアントの存在を登録するため、クライアントはセッション・マネージャに対してこのメッセージを送信しなければならない。もし前回のセッションから存在するクライアントを再開するのであれば、前回セッションで使用されていたクライアント ID を `previous-ID` 欄に入れなければならない。新規のクライアントの場合、`previous-ID` 欄のデータ長は 0 である。

もし `previous-ID` が無効な値であれば、セッション・マネージャはクライアントに対して BadValue エラーメッセージを送信する。この時点でセッション・マネージャは登録受付状態へと復帰し、次の `RegisterClient` を待つことになる。その場合、無効な `previous-ID` を送ったクライアントは、`previous-ID` 欄を空(null)にして `RegisterClient` を再送する。

    RegisterClientReply [Client ← SM]

      client-ID: ARRAY8

`client-ID` 欄には、このクライアントが使うことになる唯一無二の識別子が記されている。クライアントが `RegisterClient` メッセージの `previous-ID` 欄において識別子を指定していた場合、`client-ID` は先に指定されていたものと等しくなる。`previous-ID` が空(null)であった時は、`client-ID` にはセッション・マネージャで新たに生成した唯一無二の識別子が入る。`client-ID` の形式は第六章で規定している。

クライアントが `RegisterClient` メッセージの `previous-ID` 欄を埋めなかった場合、セッション・マネージャは `RegisterClientReply` メッセージから間を置かずに `SaveYourself` メッセージを発しなければならない。その際、この `SaveYourself` メッセージでは「type = Local」、「shutdown = False」、「interact-style = None」、「fast = False」と設定する。クライアントは、他の `SaveYourself` メッセージに対するのと同じように、このメッセージを処理する。

    SaveYourself [Client ← SM]

      type: SAVE_TYPE
      shutdown: BOOL
      interact-style: INTERACT_STYLE
      fast: BOOL

      Valid Responses:
        SetProperties
        DeleteProperties
        GetProperties
        SaveYourselfDone
        SaveYourselfPhase2Request
        InteractRequest

クライアントに状態の保存を促すため、セッション・マネージャからクライアントへこのメッセージが送られる。必要であれば、クライアントは状態を記録するファイルを編輯する。さらに必要であれば、クライアントは `SetProperties` メッセージを利用して、クライアントを再起動する際の様式や保存された状態を破棄する方法をセッション・マネージャに告知する。この処理の間、もし `interact-style` で認められていれば、セッション・マネージャへ `InteractRequest` メッセージを送ることで、クライアントは利用者と対話する許可を求めることができる。状態を保存し終えた後、もしくは状態保存が不可能な場合、プロパティが適切に設定されていれば、クライアントは `SaveYourselfDone` メッセージを発する。自分以外の他の全てのクライアントが各自状態変更を済ませた後に更なる情報保存を行いたいクライアントは、`SaveYourselfDone` の代わりに `SaveYourselfPhase2Request` を発する。この場合、クライアントは利用者とのやり取りを凍結し、 `SaveComplete`、`Die`、もしくは `ShutdownCancelled` メッセージを受信するまで待機しなければならない。

もし `interact-style` の値が `None` に設定されているのであれば、クライアントは状態保存中に利用者とやり取りしてはならない。`interact-style` の値が `Errors` の場合、異常事態が起きた時に限って、クライアントと利用者とのやり取りを認めてもよい。`interact-style` が `Any` の時は、クライアントは自由に利用者とやり取りできる。利用者との情報交換は、`InteractRequest` メッセージを送ることから始まる。`InteractRequest` を寄越したクライアントのそれぞれに対して、セッション・マネージャは `Interact` メッセージを送信する。クライアントは `Interact` メッセージが届くまで、利用者とのやり取り全てを延期しなければならない。やり取りを終えたクライアントは、セッション・マネージャへ `InteractDone` メッセージを送る。`InteractRequest` メッセージは、クライアントが `SaveYourself` を受け取ってから `SaveYourselfDone` を発するまでの間、いつでも送信することができる。

特殊な状況では、利用者と何度もやり取りをしなければならないこともあろう。`SaveYourselfDone` を送る前であれば、クライアントは `InteractRequest` - `Interact` - `InteractDone` の一連の手続きを必要なだけ実施することができる。

クライアントが、先着の `SaveYourself` に対して `SaveYourselfDone` を返していないうちに、新たな `SaveYourself` を受信した場合、まず `SaveYourselfDone` を送信しなければならない。そのようにした後には、新着の `SaveYourself` に対して適宜返答してもよい。

`type` 欄では、情報がどのような形で保存されるのかを指定する。値は `Global`、`Local`、もしくは `Both` のどれかである。 `Local` 型であれば、アプリケーションは自身の現在状態を映すようにプロパティを更新し、`SaveYourselfDone` を送信し、その上で元の処理を続行するようにしなければならない。この作業で保存される情報は、クライアントの利用者から見た状態を復元するのに十分なものであるべきであって、他の利用者から見える状態に変更を加えるものは保存を控えるべきである。利用者がクライアントに、その全てのデータを恒久的かつ広域アクセス可能な記録領域へ書き込ませたい時には、`Global` 型が選ばれる。`Both` 型であれば、クライアントは両方の作業を行う。`Both` が指定された場合、クライアントはまず恒久的な記録領域にデータを書き込み、それからセッション・マネージャのプロパティ群を更新する。

### 例

ワードプロセッサに `Local` 型の指定を付した `SaveYourself` が届いた場合、現在のファイルの内容、カーソルの位置、それ以外の現在の編輯セッションに関する情報を記載した一時的なファイルが作成される。それに続いて、ワードプロセッサは自分の `RestartCommand` プロパティと `DiscardCommand` プロパティの更新も行い、前者には件の一時的なファイルを見つけるに十分な情報を、後者には同ファイルを削除するに十分な情報を記す。

ワードプロセッサに `Global` 型の指定を付した `SaveYourself` が届いた時は、単純に編輯中のファイルを保存する。

ワードプロセッサに `Both` 型の指定を付した `SaveYourself` が届いた場合、まず編輯中のファイルを保存する。次にカーソルの位置、どのファイルを編輯していたか等を記した一時的なファイルを作る。続いて、自分の `RestartCommand` プロパティと `DiscardCommand` プロパティの更新を行い、前者には件の一時的なファイルを見つけるに十分な情報を、後者には同ファイルを削除するに十分な情報を記す。

一度セッション・マネージャからクライアントへ `SaveYourself` を送信したならば、クライアントから `SaveYourselfDone` が返されるか、セッション・マネージャから `ShutdownCancelled` を発するまで、同じクライアントに新たな `SaveYourself` を送信してはいけない。

### 実装者のために

ファイルやそれに類する外部の記録場所に対して、限局的に(local)状態を保存する場合、 一つ一つの`SaveYourself` メッセージに応じて新たな複製を作らなければならない。前に作った複製への単なる参照は認められない。なぜかというと、セッション・マネージャ側において、前に保存した状態が次の手拓(checkpoint)で必要なことに気づかず、`DiscardCommand` を通じて破棄してしまうかもしれないからである。

`shutdown` 欄には、システムが終了作業中であるか否かを記す。

### 玄論

shutdown の値によって、利用者とのやり取りは異なるものになる。

(訳註：shutdown の値が真であれば？、)クライアントは必ず状態を保存しなければならず、その後 `SaveComplete`、`Die` もしくは `ShutdownCancelled` が届くまで利用者とのやり取りを禁じなければならない。保存の後に利用者が行ったことは全て消えてしまうからである。

`fast` 欄では、クライアントができる限り急いで自身の状態を保存しなければならないのか、そうでもないのかを指定する。例えば、電源が落ちそうであることをセッション・マネージャが知っている場合、`fast` の値は `True` に設定される。

    SaveYourselfPhase2 [Client → SM]

      Valid Responses:
        SetProperties
        DeleteProperties
        GetProperties
        SaveYourselfDone
        InteractRequest

セッション・マネージャは `SaveYourselfPhase2Request` メッセージを送ってきたクライアントに対して上のメッセージを送信する。このメッセージはクライアントに次のことを通知する。即ち、他の全てのクライアントは状態変更を終えたので、それらに関わる状態情報を保存してもかまわない、ということを通知する。

### 玄論

他のクライアント群を監督するクライアント(window managers、workspace managers など)は、管理中の全てのクライアントが何時遊転(idle)状態になるのか知らなければいけない。これは監督者が各クライアントと関係のある状態情報を保存する際、その状態が途中で変わってしまう事態を避けるためである。

クライアントは、必要であれば自身の状態をファイルに書き込み、また、必要であれば、`SetProperties` を用いて、セッション・マネージャに自身の再起動様式と保存された状態情報の破棄方法とを通知する。この作業の間、クライアントは `InteractRequest` メッセージを送信して、利用者とやり取りを行うための許可を求めることができる。これを認めるのは、エラーが発生し、その解消に利用者とのやり取りが必要な時に限るべきである。状態を保存し終えた後、もしくは状態保存が不可能な場合、プロパティが適切に設定されていれば、クライアントは `SaveYourselfDone` メッセージを発する。

    SaveYourselfRequest [Client → SM]

      type: SAVE_TYPE
      shutdown: BOOL
      interact-style: INTERACT_STYLE
      fast: BOOL
      global: BOOL

      Valid Responses: SaveYourself

アプリケーションはこのメッセージをセッション・マネージャへ送信し、手拓作業(checkpoint)を要請する。この要請を受けたセッション・マネージャは、返答として `SaveYourself` メッセージを生成することができる。その際、引数欄で指定された値をそっくり流用することも可能である。

### 例

UPS (Uninterruptible Power Supply：無停電電源)の開発元は、セッション・マネージャ型のクライアントを利用して UPS の状態を監視し、もし電源が落ちそうであれば、できる限り急いで(fast)終了作業(shutdown)を実行させることができる。

もし `global` の値が `True` であれば、結果として返される `SaveYourself` は全てのアプリケーションに送信される。`global` の値が `False` であれば、結果として返される `SaveYourself` は `SaveYourselfRequest` を発したアプリケーションに対して送信される。

    InteractRequest [Client → SM]

      dialog-type: DIALOG_TYPE

      Valid Responses: Interact ShutdownCancelled

      Possible Errors: BadState (CanContinue)

手拓作業(checkpoint)やセッション保存作業の間、一度に一つのクライアントだけが利用者とやり取りする特権を与えられる。もし他のクライアントによって終了作業が取り消されていなければ、`InteractRequest` メッセージを受け取ったセッション・マネージャは、後のいづれかの時点で `Interact` メッセージを発する。

`dialog-type` 欄には `Errors` と `Normal` のどちらかを指定する。前者はクライアントにエラー時の対話画面(error dialog)を起動させたい場合に、後者は通常の対話画面を起動させたい場合に指定する。

    Interact [Client ← SM]

      Valid Responses: InteractDone

このメッセージを受け取ることで、クライアントは利用者とやり取りする特権を与えられる。利用者とのやり取りが終わった時、終了作業取消し(shutdown cancel)のメッセージが届いていなければ、クライアントはセッション・マネージャに `InteractDone` メッセージを送信しなければならない。

### 実装者のために

`Interact` メッセージを受信してから `InteractDone` を送信するまでの間に、クライアントの元に ShutdownCancelled が届いた場合、クライアントは利用者とのやり取りを切り上げて `SaveYourselfDone` を送信するものとする。

    InteractDone [Client → SM]

      cancel-shutdown: BOOL

      Valid Responses: ShutdownCancelled

このメッセージを通じて、クライアントはセッション・マネージャへ利用者との交信の完了を通知する。

`cancel-shutdown` 欄が `True` に設定されるのは、利用者が終了作業全体の取り止めを求めた時である。`Cancel-shutdown` を `True` に設定することが許されるのは、元となる `SaveYourself` メッセージの shutdown 欄に `True` が指定され、かつ、`interact-style` 欄に `Any` か `Errors` が指定されている場合に限られる。それ以外の場合には、`cancel-shutdown` の値は `False` でなければならない。

    SaveYourselfDone [Client → SM]

      success: BOOL

      Valid Responses:
        SaveComplete
        Die
        ShutdownCancelled

クライアントはこのメッセージを送信して、自身の状態を表すプロパティの全てが更新されたことを知らせる。`SaveYourselfDone` を送信した後、`SaveComplete`、`ShutdownCancelled` もしくは `Die` メッセージを受信するまで、クライアントは状態変更を控えなければならない。`SaveYourself` の作業が成功裡に終わった場合、クライアントは `success` 欄の値を `True` に設定する。そうでなければ `False` に設定する。

### 例

クライアントは、自身の状態の保存を試みて中途で記憶領域を使い切ってしまった場合、`SaveYourselfDone` メッセージの `success` 欄にて `False` を返す。

    SaveYourselfPhase2Request [Client → SM]

      Valid Responses:
        ShutdownCancelled
        SaveYourselfPhase2

クライアントはこのメッセージを送信し、他の全てのクライアントが静遊状態(quiescent)になったら知らせてもらう必要があること、それまで現状態を保持し得ることを伝える。

    Die [Client ← SM]

      Valid Responses: ConnectionClosed

セッション・マネージャは、クライアントを停止したい時、`Die` メッセージを送信する。クライアントは停止する前に `ConnectionClosed` メッセージを返信する。返信後はいつでもセッション・マネージャとの接続を断ってよい。

    SaveComplete [Client → SM]

      Valid Responses:

手拓作業(checkpoint)を終えたセッション・マネージャは各クライアントへ `SaveComplete` メッセージを送信する。以後、クライアントは自由に状態を変えることができる。

    ShutdownCancelled [Client ← SM]

進行中であった終了処理(shutdown)が中断されたことを示す。クライアントはまるで終了処理が存在しなかったかのように元の動作を続けることができる。未だ `SaveYourselfDone` を送信していないのであれば、クライアントは次の動作のどちらかを行うことができる。即ち、保存作業を中断して success 欄の値を `False` とした `SaveYourselfDone` を送信するか、もしくは、保存作業を続けて、その結果を success 欄に反映した `SaveYourselfDone` を送信する。

    ConnectionClosed [Client → SM]

      reason: LISTofARRAY8

クライアントの終了が決定したことを通知する。この後、直ちに接続を断つものとする。

`reason` 欄には、クライアントがセッションから外れる理由を、Compound Text 形式の文字列の配列で記す。クライアントの中座が利用者にとって想定されていたものであれば、大抵は ARRAY8 から成る配列の長さは 0 である。一方、クライアントが予期せぬ致命的なエラーに見舞われた場合、エラーメッセージ(通常は POSIX システムの stderr に書き込まれるもの)をセッション・マネージャへ送信する。このエラーメッセージでは一行につき一つの ARRAY8 が当てられる。`reason` 欄の内容を利用者に表示するのはセッション・マネージャの仕事である。

このメッセージを送り出した後、当のクライアントはセッション・マネージャに対して追加の XSMP メッセージを送信してはならない。

### 実装者のために

追加のメッセージが届いた場合は破棄すること。

### 玄論

実際に接続を断つのに先立って `ConnectionClosed` メッセージを送信する理由は、伝送方式(transport protocols)の中には接続の切断を直ちに通知しないものが存在するからである。

    SetProperties [Client → SM]

      properties: LISTofPROPERTY

指定されたプロパティ群のそれぞれに指定された値を設定する。既存のプロパティの中、`SetProperties` メッセージで挙げられなかったものは変化しない。予め役割を決められているプロパティも存在する。第十一章 予め定義されているプロパティ群 を見よ。

プロトコルの仕様として、標準で定義されていないプロパティの名前には頭にアンダースコアを付けるよう勧告している。組織間での衝突を防ぐために、接頭辞を付加する(例、_KPC_FAST_SAVE_OPTION)。組織用の接頭辞は X Registry に登録するものとする。アンダースコア以外の文字から始まるプロパティ名は全て、XSMP で将来使用されるかもしれないので、使わずに残しておく。

    DeleteProperties [Client → SM]

      property-names: LISTofARRAY8

名前が挙ったプロパティを削除する。

    GetProperties [Client → SM]

      Valid Responses: GetPropertiesReply

このメッセージを発したクライアントの全プロパティの値を寄越すよう、セッション・マネージャに要請する。

    GetPropertiesReply [Client ← SM]

      values: LISTofPROPERTY

このメッセージは `GetProperties` メッセージに対する返信であり、全プロパティの `values` (訳註：名前、型、値？)が入っている。

## 第八章 エラー

メッセージの受信側で異常事態に気づいた時は、受信側から送信元へ ICE エラーメッセージを送る。XSMP で使用するエラーは二種類しかない。BadValue と BadState である。両方とも ICE プロトコルで定義されている。

送受信の文脈に沿わないメッセージが届いた場合、BadState エラーメッセージを出す。

## 第九章 状態遷移表

以下の状態遷移表には、クライアントとセッション・マネージャ双方の全ての動作が記載されている。(訳註：そうでもない。)

## Client State Diagram

start:
ICE protocol setup complete → register

register:
send RegisterClient → collect-id

collect-id:
receive RegisterClientReply → idle

shutdown-cancelled:
send SaveYourselfDone → idle

idle: [Undoes any freeze of interaction with user.]
receive Die → die
receive SaveYourself → freeze-interaction
send GetProperties → idle
receive GetPropertiesReply → idle
send SetProperties → idle
send DeleteProperties → idle
send ConnectionClosed → connection-closed
send SaveYourselfRequest → idle

die:
send ConnectionClosed → connection-closed

freeze-interaction:
freeze interaction with user → save-yourself

save-yourself:
receive ShutdownCancelled → shutdown-cancelled
send SetProperties → save-yourself
send DeleteProperties → save-yourself
send GetProperties → save-yourself
receive GetPropertiesReply → save-yourself
send InteractRequest → interact-request
send SaveYourselfPhase2Request → waiting-for-phase2
save-yourself:
if shutdown mode:
send SaveYourselfDone → save-yourself-done
otherwise:
send SaveYourselfDone → idle

waiting-for-phase2:
receive ShutdownCancelled → shutdown-cancelled
receive SaveYourselfPhase2 → phase2

phase2:
receive ShutdownCancelled → shutdown-cancelled
send SetProperties → save-yourself
send DeleteProperties → save-yourself
send GetProperties → save-yourself
receive GetPropertiesReply → save-yourself
send InteractRequest → interact-request (errors only)
if shutdown mode:
send SaveYourselfDone → save-yourself-done
otherwise:
send SaveYourselfDone → idle

interact-request:
receive Interact → interact
receive ShutdownCancelled → shutdown-cancelled

interact:
send InteractDone → save-yourself
receive ShutdownCancelled → shutdown-cancelled

save-yourself-done: (changing state is forbidden)
receive SaveComplete → idle
receive Die → die
receive ShutdownCancelled → idle

connection-closed:
client stops participating in session

## Session Manager State Diagram

start:
receive ProtocolSetup → protocol-setup

protocol-setup:
send ProtocolSetupReply → register

register:
receive RegisterClient → acknowledge-register

acknowledge-register:
send RegisterClientReply → idle

idle:
receive SetProperties → idle
receive DeleteProperties → idle
receive ConnectionClosed → start
receive GetProperties → get-properties
receive SaveYourselfRequest → save-yourself
send SaveYourself → saving-yourself

save-yourself:
send SaveYourself → saving-yourself

get-properties:
send GetPropertiesReply → idle

saving-get-properties:
send GetPropertiesReply → saving-yourself

saving-yourself:
receive InteractRequest → saving-yourself
send Interact → saving-yourself
send ShutdownCancelled → idle
receive InteractDone → saving-yourself
receive SetProperties → saving-yourself
receive DeleteProperties → saving-yourself
receive GetProperties → saving-get-properties
receive SaveYourselfPhase2Request → start-phase2
receive SaveYourselfDone → save-yourself-done

start-phase2:
全クライアントが SaveYourselfPhase2Request、SaveYourselfDone のどちらかの送信を済ませている場合:
send SaveYourselfPhase2 → phase2
その他の場合
→ saving-yourself

phase2:
receive InteractRequest → saving-yourself
send Interact → saving-yourself
send ShutdownCancelled → idle
receive InteractDone → saving-yourself
receive SetProperties → saving-yourself
receive DeleteProperties → saving-yourself
receive GetProperties → saving-get-properties
receive SaveYourselfDone → save-yourself-done

save-yourself-done:
If all clients are saved:
If shutting down:
send Die → die
otherwise
send SaveComplete → idle
If some clients are not saved:
→ saving-yourself

die:
セッション・マネージャは接続受入れを止める。

## 第十章 プロトコルの符号表

## 型

BOOL
0 | False
1 | True

INTERACT_STYLE
0 | None
1 | Errors
2 | Any

DIALOG_TYPE
0 | Error
1 | Normal

SAVE_TYPE
0 | Global
1 | Local
2 | Both

ARRAY8 |
4 | CARD32 | 配列の長さ
n | ListofCARD8, 配列 | p = pad (4 + n, 8)
2 | Both |

LISTofARRAY8 |
4 | CARD32 | 個数
4 |  | 使わない
a | ARRAY8 | 最初の配列
b | ARRAY8 | 二番目の配列
. |  |
. |  |
. |  |
q | ARRAY8 | 最後の配列

PROPERTY |
a | ARRAY8 | 名前
b | ARRAY8 | 型 (Latin-1 で符号化された XPCS、大文字小文字を区別)
c | LISTofARRAY8 | 値

LISTofPROPERTY |
4 | CARD32 | 個数
4 |  | 使わない
a | PROPERTY | 最初のプロパティ
b | PROPERTY | 二番目のプロパティ
. |  |
. |  |
. |  |
q | PROPERTY | 最後のプロパティ

## メッセージ

XSMP は ICE の下位プロトコルである。主たる命令コードは ICE によって実行時に割り当てられるので、以後の説明では「`?`」で表記する。

XSMP の手続きはクライアントがサーバへ ICE `ProtocolSetup` メッセージを送信することから始まる。protocol-name 欄に「`XSMP`」と記し、プロトコルの主たる版番号には 1、従たる版番号には 0 を指定する。これらの値はプロトコルの改訂によって変更されることがある。前の版との互換性を保った改訂であれば従たる版番号を一つ増やし、そうでなければ主たる版番号を一つ増やす。

セッション・マネージャが発する ICE の `ProtocolReply` メッセージにおいて、XSMP 側に定義を委ねている箇所がある。XSMP では、vendor 欄をセッション・マネージャの製品識別子として、release 欄をセッション・マネージャのソフトウェアの版識別子として定義する。ICE `ProtocolReply` メッセージ内のこの情報を埋めるのはセッション・マネージャの仕事である。

`RegisterClient`
1 | ? | XSMP
1 | 1 | opcode
2 |  |
4 | a/8 | 残りのデータの長さ。8バイトが単位
a | ARRAY8 | previous-ID

`RegisterClientReply`
1 | ? | XSMP
1 | 2 | opcode
2 |  |
4 | a/8 | 残りのデータの長さ。8バイトが単位
a | ARRAY8 | client-ID

`SaveYourself`
1 | ? | XSMP
1 | 3 | opcode
2 |  |
4 | 1 | 残りのデータの長さ。8バイトが単位
1 | SAVE_TYPE | type
1 | BOOL | shutdown
1 | INTERACT_STYLE | interact-style
1 | BOOL | fast
4 |  |

`SaveYourselfRequest`
1 | ? | XSMP
1 | 4 | opcode
2 |  |
4 | 1 | length of remainning data in 8-byte units
1 | SAVE_TYPE | type
1 | BOOL | shutdown
1 | INTERACT_STYLE | interact-style
1 | BOOL | fast
3 |  |

`InteractRequest`
1 | ? | XSMP
1 | 5 | opcode
1 | DIALOG_TYPE | dialog type
1 |  |
4 | 0 | 残りのデータの長さ。8バイトが単位

`Interact`
1 | ? | XSMP
1 | 6 | opcode
2 |  |
4 | 0 | 残りのデータの長さ。8バイトが単位

`InteractDone`
1 | ? | XSMP
1 | 7 | opcode
1 | BOOL | cancel-shutdown
1 |  |

`InteractDone`
1 | ? | XSMP
1 | 7 | opcode
1 | BOOL | cancel-shutdown
1 |  |
4 | 0 | 残りのデータの長さ。8バイトが単位

`SaveYourselfDone`
1 | ? | XSMP
1 | 8 | opcode
1 | BOOL | success
1 |  |
4 | 0 | 残りのデータの長さ。8バイトが単位

`Die`
1 | ? | XSMP
1 | 9 | opcode
1 |  |
4 | 0 | 残りのデータの長さ。8バイトが単位

`ShutdownCancelled`
1 | ? | XSMP
1 | 10 | opcode
2 |  |
4 | 0 | 残りのデータの長さ。8バイトが単位

`ConnectionClosed`
1 | ? | XSMP
1 | 11 | opcode
2 |  |
4 | a/8 | 残りのデータの長さ。8バイトが単位
a | LISTofARRAY8 | reason

`SetProperties`
1 | ? | XSMP
1 | 12 | opcode
2 |  |
4 | a/8 | 残りのデータの長さ。8バイトが単位
a | LISTofPROPERTY | properties

`DeleteProperties`
1 | ? | XSMP
1 | 13 | opcode
2 |  |
4 | a/8 | 残りのデータの長さ。8バイトが単位
a | LISTofPROPERTY | properties

`GetProperties`
1 | ? | XSMP
1 | 14 | opcode
2 |  |
4 | 0 | 残りのデータの長さ。8バイトが単位

`GetPropertiesReply`
1 | ? | XSMP
1 | 15 | opcode
2 |  |
4 | a/8 | 残りのデータの長さ。8バイトが単位
a | LISTofPROPERTY | properties

`SaveYourselfPhase2Request`
1 | ? | XSMP
1 | 16 | opcode
2 |  |
4 | 0 | 残りのデータの長さ。8バイトが単位

`SaveYourselfPhase2`
1 | ? | XSMP
1 | 17 | opcode
2 |  |
4 | 0 | 残りのデータの長さ。8バイトが単位

`SaveComplete`
1 | ? | XSMP
1 | 18 | opcode
2 |  |
4 | 0 | 残りのデータの長さ。8バイトが単位

## 第十一章 予め定義されているプロパティ群

一つのプロパティが保持する値(values)は全て、一個の LISTofARRAY8(ARRAY8 の配列)に格納される。プロパティの型(type)が「CARD8」であれば、値を格納する LISTofARRAY8 は一個の ARRAY8 から成り、その ARRAY8 の長さは1バイトである。そして、この1バイトに CARD8 型で表される値が入る。プロパティの型が ARRAY8 であれば、LISTofARRAY8 はただ一つの ARRAY8 から成り、そこに値が格納される。

クライアントがセッション・マネージャに接続する度に、必要なプロパティを設定しなければならない。プロパティの設定は、クライアントが `RegisterClient` を送信してから、同者が `SaveYourselfDone` を送信するまでの間に行われなければならない。この間を外した場合のセッション・マネージャの挙動は定義しない。

クライアントは標準で用意されていないプロパティも設定し、取得し、削除することができる。作成したプロパティの寿命を次のセッションまで延ばすことはできない。

Name | Type | Posix Type | Required?
--- | --- | --- | ---
CloneCommand | OS-specific | LISTofARRAY8 | Yes
CurrentDirectory | OS-specific | ARRAY8 | No
DiscardCommand | OS-specific | LISTofARRAY8 | No*
Environment | OS-specific | LISTofARRAY8 | No
ProcessID | OS-specific | ARRAY8 | No
Program | OS-specific | ARRAY8 | Yes
RestartCommand | OS-specific | LISTofARRAY8 | Yes
ResignCommand | OS-specific | LISTofARRAY8 | No
RestartStyleHint | CARD8 | CARD8 | No
ShutdownCommand | OS-specific | LISTofARRAY8 | No
UserID | ARRAY8 | ARRAY8 | Yes

* 外部の保管場所(例えば状態ファイル)に記録されている状態情報がある場合、必須となる。

CloneCommand | 再起動するのがアプリケーションの複製であるという点を除けば、`RestartCommand` と同じようなものである。唯一の相違点は、アプリケーションの登録時にクライアント ID を申告しないことである。POSIX システムにおいては、型(type)は LISTofARRAY8(ARRAY8 の配列)とする。
CurrentDirectory | POSIX に準拠したシステムにおいては、現在のディレクトリを表す値が入る。この値はプログラムを起動する前に設定する必要があり、プロパティの型は ARRAY8 である。
DiscardCommand | このプロパティに入っている命令がクライアントの稼働しているホスト(接続から判断)に届くと、その時点の状態に関するあらゆる情報が破棄される。この命令が定められていなければ、セッション・マネージャはクライアントの状態情報の全てが `RestartCommand` に記述されているものと考える。POSIX システムでは、プロパティの型は LISTofARRAY8 とする。
Environment | POSIX に準拠したシステムにおいては、このプロパティの型は LISTofARRAY8 になる。配列中の ARRAY8 には、環境変数名とその値とが交互に格納される。
ProcessID | ここに OS 独自のプロセス識別子を記す。POSIX システムにおいては ARRAY8 型とし、getpid() 関数の戻り値を Latin-1 文字列(10進数表記)に変換したものを入れる。
Program | 実行中のプログラムの名前。POSIX システムにおいては、この名前に execve 関数への第一引数の値を用いる。プロパティの型は ARRAY8 とする。
RestartCommand | このプロパティに入っている命令がクライアントの稼働しているホスト(接続から判断)に届くと、クライアントが記録時の状態で再起動される。POSIX 準拠のシステムにおいては、プロパティの型は LISTofARRAY8 であり、この配列の各要素を以て argv 配列の各要素を表す。この再開命令は、クライアントが確実に指定されたクライアント ID で起動されるように記述するものとする。
ResignCommand | `RestartStyleHint` プロパティを `RestartAnyway` に設定したクライアントでは、このプロパティに次の命令を記述する。即ち、クライアントの動作結果を取り消し、保存された状態を消去する命令を記述する。 ### 例 利用者が xmodmap を実行する。xmodmap をセッション・マネージャに登録し、`RestartStyleHint` プロパティに `RestartAnyway` を設定し、そして xmodmap を終了する。利用者の要請を受けてセッション・マネージャがこの動作を取り消し得るように、xmodmap は動作結果を取り消す命令を `ResignCommand` に登録する。
RestartStyleHint | RestartStyleHint プロパティが設けられている場合、そこにはクライアントの好む再起動様式が入っている。もしこのフラグが指定されていなければ、値は `RestartIfRunning` と見做される。以下がプロパティの値の候補である。
Name | Value
--- | ---
RestartIfRunning | 0
RestartAnyway | 1
RestartImmediately | 2
RestartNever | 3
通常は `RestartIfRunning` 方式を用いる。クライアントが前回のセッションの終了時点でセッション・マネージャに接続されていた場合、次のセッションで同クライアントを再起動する。 `RestartAnyway` 方式の指定をセッション・マネージャは次のように理解する。クライアントが現セッションの終了以前に停止していても、次のセッションで再起動するべきである、と。これがあくまで示唆に過ぎず、セッション・マネージャはどのアプリケーションを再起動させるかについて利用者の定めた方針に従う、ということに注意する。 ### 玄論 この値を指定するクライアントは以下のものがある。例えば、(MS-Windows のクライアントのような形で)終了作業中に利用者が再起動の必要性を表明する手段の備わったクライアント。また、他のクライアントを起動した後に消え去るが、次回も再起動されるクライアント。 `RestartAnyway` を指定したクライアントにおいては、`ResignCommand` プロパティと `ShutdownCommand` プロパティに対して、クライアント終了後に状態情報を元に戻すための命令を設定するものとする。 `RestartImmediately` 方式は `RestartAnyway` に似ている。しかし前者は、後者の示唆するものに加えて、クライアントが間を置かずに実行されることをも含意している。クライアントが終了したら、セッション・マネージャは現行のセッション内で同クライアントの再起動を図るものとする。 ### 実装者のために 病躯のクライアントが何度も繰り返し再起動されないように、`RestartImmediately` を指定したクライアントの再起動頻度を見て、正常かどうかを調べるのが賢いやり方である。 `RestartNever` 方式が意味するのは、クライアント側が次のセッションで再起動されることを望んでいないということである。 ### 実装者のために これを用いるべき場面はほとんどない。`RestartNever` が指定された場合、セッション再開時にクライアントが何の徴しもなくセッションから外れてしまい、利用者は困惑するであろう。
ShutdownCommand | この命令はセッション終了時に実行される。`RestartStyleHint` を `RestartAnyway` に設定したクライアントは停止した後も状態情報を持ち続けるので、そうしたクライアントの後片付けを行う。そのようなクライアントも依然としてセッションの一員なので、クライアントは保存済みの如何なる状態情報も消去してはならない。 ### 例 起動時にカメラを立ち上げる機能を持ったクライアントを実行する。その後直ぐクライアントは停止する。利用者はセッション終了時にカメラを切りたい。このクライアントは、`RestartStyleHint` を `RestartAnyway` に設定し、カメラを切るための `ShutdownCommand` を登録する。
UserID | 利用者の ID を記す。POSIX に準拠したシステムにおいては、ここに利用者の名前(struct passwd の `pw_name` 部)が入る。

入り口に戻る