要約

  • Gopherの一項目はtype、表示名、opaque selector、host、portを持った。人が表示名を選ぶと、clientは残りのfieldを使って新しい接続を開いた。
  • 見かけのdirectory treeは、独立した運営者へのreferralから成るgraphだった。menuを作る者は経路を提示できても、宛先を所有せず、返却内容の真正性や継続性も証明しなかった。

「次の階層」は別の管理者かもしれない

大学の案内menuで「講義日程」を選ぶ。利用者には、同じsystem内のfolderを一段降りたように見える。だがclientは、その直前まで話していたserverを離れ、別のhostの別portへ接続しているかもしれない。その指示は、画面に出ない部分を含む一行の中にあった。

RFC 1436のdirectory entityは簡潔である。先頭一文字のitem type、利用者向けname、Tab、selector、Tab、host、Tab、port、そしてCRLF。通常、利用者が見るのはnameだけだ。clientは残りを次のtransactionの実行表として扱う。

この仕組みなら、学部Aが学部Bの資料を中央serverへ複製する必要はない。menuに一行を置けばよい。clickの後、clientが記載先へ直接問い合わせる。統一された見た目は、統一されたstorageからではなく、referralから生まれた。

同時に権限も限定された。menu運営者はlabel、順序、掲載の有無を決められる。しかし遠隔serverでselectorを解釈し、responseを作るのは別のoperatorである。案内を掲載した事実は、案内先の所有を意味しない。

Selectorを理解しないことが互換性だった

例示されたselectorはpathらしく見えることが多い。それでもRFC 1436は、clientにとってselectorは意味を持つべきでなく、変更してはならないとした。

この抑制によってserver側の自由が残った。ある実装はfile pathとして扱い、別の実装はscript、application、queryとして扱える。共通protocolは、内部filesystemの公開や世界共通object IDを要求しない。

Opaqueであることは、永続性や安全性を意味しない。同じbyte列でもhostが違えば別物を示す。同じhostでも移行後に意味が変わり得る。Selectorはcontent hashでもcredentialでもない。指定されたendpointのlocal grammarに入力される文字列である。

したがって運用記録には正確なbyteを残す必要がある。slashを正規化したり、独自encodingを推測して直したりすれば、別objectを要求する可能性がある。clientが賢くあるためには、どのlayerで解釈しないかを知る必要があった。

Rootは支配者ではなく入口だった

Gopherがfilesystemの比喩を選んだのは、階層が理解しやすいからである。実networkがtreeである必要はなかった。menuはsecondary server、Internet上の任意のservice、既に通ったnodeへもlinkできる。RFCはこの構造をarbitrary graphとして説明する。

campusは著名なtop-level serverを置き、各部門の入口を登録できた。負荷分散のためcloneを使うこともできた。しかし部門は自分のmenuから他serverへ直接linkできた。rootは発見を容易にする地点であって、到達可能な全contentの所有者ではない。

一回の遷移には複数の管理面がある。元menuは表示名とdescriptorを作る。宛先operatorはselectorの意味を決める。DNS operatorはaliasを別addressへ移せる。port上のprocessが実際の応答者になる。clientはtypeを理解するか決め、readerは表示された範囲で選ぶ。

ゆえにmenu行は「この時点で、このsourceがこの経路を提示した」という証拠にすぎない。hostの誤記、古いselector、誤解を招くlabel、変化したDNSはいずれも起こり得る。graphの継続は中央authorityではなく、別々の当事者の継続的協力に依存した。

Browseの連続性はclientが持っていた

base transactionは短い。TCPを開き、空でもよいselector行を送る。serverはresponseを返すが、transaction間にclient stateを保持しない。CRLFだけならtop-level menuを求められる。

textとmenuは、一文字のperiodだけを置いたlineで終わる。本文がperiodで始まる場合はもう一つ加え、clientが余分を外す。binary itemではperiodを使わず、TCP closeが終端になる。

この差は「closeは失敗」という単純化を禁じる。binaryでは正常なboundaryになり得る。一方、正しいperiodを受け取っても意味の正しさは分からない。完成したmenuがdead linkを含むことも、完成したtextが期待外れであることもある。

一つのsessionに見えるのはclientの働きだった。RFC 1436は訪問地点をstackして戻る方法や、directoryをcacheする方法を示す。複数serverが同じ利用履歴を共有する必要はない。旅程は独立したexchangeとlocal memoryから再構成された。

Typeは処理方法を選び、真偽を判定しない

行頭のtypeはclientの動作を変える。0はtext、1はmenu、7はindex searchである。他の文字はbinary、CSO、Telnet、TN3270などを示す。未対応のnon-core typeは無視しても、unknownとして示してもよい。

この一文字はformatの証明でも安全表示の許可でもない。dispatchのhintである。誤ったtypeが付けば、到達可能なendpointに対して間違ったtransactionを始める可能性がある。

type 7では、clientはselector、Tab、search stringを送る。serverは一致結果をvirtual menuとして返す。複数indexやgatewayが別々のcollectionを扱っても、client側の形は同じでよい。

検索結果も二段階のreferralである。search serverがmatchを判断してdescriptorを返し、宛先serverがretrievalを支配する。結果掲載は、到達性、rankingの妥当性、最終documentの同一性を保証しない。

URIは経路を保存したが、内容を固定しなかった

RFC 1738はGopher routeをURLにした。host、optional port、一文字のgophertype、selectorである。port省略時は70、path省略時はtype 1のtop-level menuになり、encoded Tabがsearch stringを分けた。

RFC 4266は後にこのschemeをStandards Track上へ残した。menuを保持しなくても、経路をbookmarkし、別の人へ渡せるようになった。

しかしURIはobjectを凍結しない。Selectorの意味はserverに残り、DNSは変わり、port上のprocessも交代する。再現できるのはrequest syntaxであって、同じ効果や同じcontentではない。

securityも追加されなかった。RFC 1436はsecurity issuesを扱わないと明記する。RFC 4266は後に、privacyがなく、password使用もcleartextで現代的には危険だと記した。正しくparseできることと、安全なchannelであることは別である。

小さな一行が分権の形を決めた

多数のpublisherを一つの閲覧空間へまとめながら、serverとcontentを一人のadministratorへ渡さないにはどうするか。Gopherは、次のactorの座標をclientへ渡した。

もちろん集中は起こり得る。人気menuはvisibilityを左右し、indexは収集範囲を決め、clientは非対応typeを隠せる。それでも各権限のownerを分けて問うことができる。

ここに残る教訓は、catalogueとdestinationの区別である。経路を記録する者は、到達先を見つけやすくする。だが住所録を管理することは、記載された建物を所有することではない。

出典