要約

  • RFC 3391 は複数の MIME メッセージを番号と長さを持つチャンクへ分割し、ルート文書中の参照の直前または直後に画像を置けるよう、それらを交互に並べた。
  • 近接配置は生成側の予測にすぎず、受信側のレイアウト順、記憶容量、破棄時点を知らせるものではない。局所的に正しいチャンクでも、全体の資源消費は膨らみ得た。

一枚ずつ原稿を読み取るスキャナーと、届いたページから印刷したいプリンターを考える。スキャナーは、そのページを作るまで必要な画像を知らない。ところが複合データを単純に並べると、画像を本文の前へ全て置くか、本文の後ろへ全て置くかという窮屈な選択になる。

前置きすれば、生成側は画像を先に発見しなければならず、受信側は用途が来るまで保持する。後置きすれば、最初のページに必要な画像でさえ、長いルート文書が終わるまで届かない。multipart/related は関係を表現できても、その順序が逐次処理に適するとは限らなかった。

2002 年 12 月に Informational RFC として公開された RFC 3391 は、application/vnd.pwg-multiplexed という別の表現を定義した。複合オブジェクトを構成する MIME メッセージをチャンクへ分け、異なるメッセージのチャンクを一つのストリーム上で交互に送る。ルートを途中で止め、参照される画像を挟み、再びルートを続けられる。

ここで変わったのはオブジェクトの意味ではない。RFC は、ルートや画像という「構成要素」と、それらを運ぶ「メッセージ」を区別した。再構成された各メッセージは、同じ構成要素を multipart/related で表した body part とオクテット単位で同一になる想定だった。意味を作り直すのではなく、到着順だけを組み替えたのである。

チャンクの先頭行には CHK、メッセージ番号、ペイロード長、MORE または LAST が並ぶ。長さが次のペイロード境界を決め、MORE は同じメッセージの続き、LAST はその終端を示す。別メッセージの断片が間に入っても、一つのメッセージ内の順序は崩せない。

最初のチャンクはルートメッセージの全部または一部を含む。ただし長さゼロも許されるため、実際の先頭オクテットが後で現れる構成も可能だった。エンティティ全体は CHK 0 0 LAST で閉じる。番号 0 はこの最終チャンクのために予約された。

終端記号があれば、それ以前が自動的に完全になるわけではない。全メッセージの LAST より先に最終チャンクが現れた場合、受信側の動作は未定義である。メッセージ番号の再利用も禁止ではなく非推奨だった。再利用するなら、先のメッセージを閉じてから同じ番号の次を始める必要がある。

必須の type パラメータはルートメッセージのメディアタイプを宣言する。内側を読む前に複合オブジェクトの種類を判断できる一方、宣言と実際の Content-Type が食い違えば動作は未定義になる。Content-ID や Content-Location による関連付けは MHTML の慣行を利用できたが、RFC 3391 自体が関係の意味を発明したわけではない。

印刷の例では、長いページ記述の途中に画像への最初の参照が現れる。その直前に画像メッセージを置けば、プリンターが参照へ到達した時点で画像は既にある。根全体を待つ必要も、未来の画像を全て先に抱える必要もない。

スキャンの例では、画像を参照の直後へ置く方法も使える。受信側は配置情報を先に知り、次に実体を受け取る。参照と実体の間のオクテット距離を短くすることで、双方が仕事全体をため込まずに進められる可能性が生まれた。

しかし、受信側がレイアウトを決める例では、生成側の視界が途切れる。横並びの画像を帯状に交互送信すると、十分なメモリーがある間は効率的に見える。途中で容量が尽きれば、複数画像の未完成部分だけが交互に残る。RFC はこの場面で画像をインターリーブしないよう勧めた。

回り込み文字はさらに難しい。生成側には、受信側の書体やページ幅によって回り込みがどこで終わるか分からない。文字チャンクを早く切れば、画像全体を保持するか、回り込みを途中で諦めることになる。遅く切れば、余分な文字を保持し、画像の位置が後ろへずれるかもしれない。画像より文字の方が小さいことが多いため、RFC はやや多めの文字を先に送る戦略を示した。それでも推測は推測である。

この限界を IESG Note は冒頭で明文化した。生成側が受信側の能力と制約を十分に知っている場合にのみ、このメディアタイプは適切だという。読み手が違えば必要な物も時点も異なるのに、この仕組みにはそれを問い合わせる方法がない。未知の相手には、BEEP のような双方向手段を検討すべきだとした。

一方向の多重化は、生成側に優れた先回りを与える。双方向通信は、受信側に要求権を与える。要求してから転送すれば待ち時間が生じるかもしれず、先に押し込めば予測を外すかもしれない。速度を優先する既知の高速プリンターと、多様な読み方を持つ未知の消費者では、適切な制御面が違う。

表示についても受信側が権限を持った。コンテナとルートタイプの双方を理解する場合、構成要素は複合オブジェクトの文脈で表示される。このとき各メッセージの Content-Disposition は冗長または誤解を招き得るため、表示目的では無視する。コンテナだけを理解する場合は、全体を抑止するか、各メッセージを混合添付として扱う。コンテナ自体を知らなければ不透明なデータでしかない。

セキュリティ節は、見えない受信側へ予定を押し込む危険を列挙した。故障した、あるいは悪意ある生成側は、一つのメッセージの断片を大量のオクテットで隔て、最後の断片を送らないことができる。多数のメッセージを同時に開いたままにし、到着しない構成要素を参照し、破棄可能と分かる前に大量の資源を届けることもできる。

個々のチャンクが正しくても安全とは限らない。番号、長さ、継続状態が全て妥当でも、未完了の約束が積み上がれば受信側の保存量は増え続ける。構文検証は、資源上限の証明ではなかった。

Lu Heng の Minimum Initial Specification から見ると、共通仕様の境界は明快だ。番号、長さ、継続、ルート、終了という再構成の条件だけを共有し、メモリー管理やレイアウトは端点へ残す。その余白によって、受信実装は中央の許可なしに改善できる。

Running-Code Primacy は、証明の範囲をさらに限定する。メディアタイプ登録は、実機が止まらず印刷した証拠ではない。LAST の受信も、画像が正しく置かれた証拠ではない。元のストリーム、参照関係、バッファー推移、出力結果を観測して初めて運用上の主張が成立する。

RFC 3391 が制御できたのは、画像を参照の近くへ運ぶことだった。読み手がいつ手を伸ばし、どこへ置き、いつ捨てるかまでは見えない。近さは設計できる。需要を知るには、別の往復が要る。

出典