Message-Id: <9408120421.AA14175@goldman.gnu.ai.mit.edu> To: ctcp@kei.com Subject: REVISED AND UPDATED CTCP SPECIFICATION Newsgroups: alt.irc.ircii,alt.irc Subject: REVISED AND UPDATED CTCP SPECIFICATION Distribution: --text follows this line-- 私はZenIRCクライアントのドキュメント化の一部として、暫くの間IRCアーカイブ サイトの辺りにあった2冊のテキストファイル(ctcp.docとdcc.protocol)を拡張 し改訂して合併しました。Klaus Zeugeのファイル"ctcp.doc"は、DCC以外にも基礎 的なCTCPプロトコルとほとんどのCTCPコマンドについて記述されていました。Troy Rolloが書いた"dcc.protocol"ファイルは、CTCP DCCメッセージの記述以外にも、 DCC CHATとDCCファイル転送で使用されるプロトコルを含んでいました。私は二部 のドキュメントをくっつけて、わかりやすくするためにそれらを編集し、ZenIRCク ライアントにCTCPを実装する間に不明瞭に感じたところについても詳しく書きまし た。 結果はなお完璧には遠いですが、私は結果がオリジナルの2部のドキュメントより 有用だと信じていますので、IRCアーカイブの管理者に"ctcp.doc"と"dcc.protocol" を、拡張し改訂された"ctcp.doc"ファイルに交換するか補足するように促していま す。 ZenIRCクライアントのアルファテストバージョンはalpha.gnu.ai.mit.eduの中の /zenirc/zenirc.tar.gzから利用可能です。 コメント、批判、提案は直接私にお願いします。私はalt.irc*を見てませんので。 (訳注:もちろんBen氏へです。) --Ben --------------------------------[きりとり線]-------------------------------- ;;; hey emacs, this is -*-Text-*- Klaus Zeuge Troy Rollo Ben Mesander クライアント−クライアント間プロトコル(CTCP) クライアントからクライアントへのプロトコルとは次のようなやり方で使用するとい う意味です。 1/ 通常は、ユーザーのクライアント間で構造化されたデータ(グラ フィックや音声、それから異なるフォント情報のような)を送信 します。そして特別な場合には 2/ ユーザーのクライアントに答えてもらうための問い合わせをします。 ********************************************** クライアントとサーバーの間の基本的なプロトコル ********************************************** インターネットリレーチャット(IRC)のクライアントとサーバーの間の文字は8ビッ トのバイト(いわゆるオクテット)で、8進法で\000から\377を全て含んだ数値を持 つことができます(10進数で0〜255)。いくつかの文字は特別で: CHARS ::= '\000' .. '\377' NUL ::= '\000' NL ::= '\n' CR ::= '\r' 注: この文の中では'\'に3つの数字を続けて8進法の値を表すのに使います。'\' にアルファベットを続けてC言語スタイルの特殊文字を表すのに使います。 そして、'..'は一連の文字を表します。 サーバーへ送ったか、またはサーバーから受信した行(ここでは”低レベルメッセ ージ”と呼びます)はNLかCRを追加した0個以上のオクテット(NUL、NL、CRを除く) から成り立っています。 (訳注:現在のIRCの仕様では一行の終わりには一組のCRLFを追加する事になって います。ここで言う低レベルメッセージとはIRCとやりとりされる行のことです。) L-CHARS ::= '\001' .. '\011' | '\013' | '\014' | '\016' .. '\377' L-LINE ::= L-CHARS* CR LF 注: '*'はここでは「0個以上の直前の文字集合」を、'|'はその前後の集まりが交 換可能だということを表すために使われています。 NULはサーバーへは送られません。 ********************** 低レベルクォーティング ********************** IRCサーバーとやりとりするメッセージにNULやNLやCRを含むことができなくても、 クライアント間ですべての文字(”中間レベルメッセージ”と呼ばれる)が送れる ことは、やはり望ましい事だと思われます。これを可能にするためには、その3文 字をクウォートしなければなりません。そういうわけでクォート文字が必要になり ます。もちろん、そのクォート文字自身も帯域内なので、クォート文字自体もクォー トしなければなりません。 M-QUOTE ::= '\020' (CNTRL/Pコードです) 中間レベルメッセージを送信するとき、メッセージの中に{NUL,NL,CR,M-QUOTE}の どれかの文字があれば、次の表で2文字のシーケンスと取り替えられます: NUL --> M-QUOTE '0' NL --> M-QUOTE 'n' CR --> M-QUOTE 'r' M-QUOTE --> M-QUOTE M-QUOTE 低レベルメッセージを受信する時には、中間レベルメッセージにするために、 M-QUOTEがあればその次の文字を見て、その2文字を次の表で交換します: M-QUOTE '0' --> NUL M-QUOTE 'n' --> NL M-QUOTE 'r' --> CR M-QUOTE M-QUOTE --> M-QUOTE M-QUOTEに後続する文字がリストのどの文字でも無い場合にははエラーになります。 その時には、メッセージからM-QUOTE文字を落として、オプションでユーザーにそ のことを警告してください。例えばサーバーから文字列 'x' M-QUOTE 'y' 'z'が来 た時には、'x' 'y' 'z' にしてください。 低レベルクォートする前のサーバーへのメッセージ(反対方向の時は、サーバーか らのメッセージを低レベルデクォーティングした後)は、次のように見えます: M-LINE ::= CHARS* ************** タグ付きデータ ************** クライアントの間の拡張データと、問い合わせ/返答のペアを両方とも送信するた めに、拡張データフォーマットが必要になります。拡張データは、中間レベルメッ セージ(低レベルメッセージのテキスト部分を低レベルクォーティングした後)の テキスト部分として送られます。 中間レベルメッセージの内部の拡張データを送信するために、それを区切る方法が 必要です。それは拡張データの始めと終了の位置に区切り文字を置くことで実現し ます。区切り文字は次のように定義されます: X-DELIM ::= '\001' スタートと終了の区切り文字は同様にみえるので、最初のX-DELIMは奇数区切り文 字、その次は偶数区切り文字と呼びます。更にその次のは奇数区切り文字、次は偶 数、と続きます。 データがクォートされる場合(反対の場合は、デクォートされる前)、X-DELIMペ アの内側の拡張データの中では、X-DELIM以外の全ての種類の文字を使用すること ができます。 X-CHR ::= '\000' | '\002' .. '\377' 拡張メッセージは、空(奇数、偶数区切り文字の間に何も無い)か、1つ以上の空 白でない文字(\040以外の全て文字)か、一文字以上の空白文字の後に空白が続い てその後に0個以上の文字が後続するもの、のうちのどれかになります。 X-N-AS ::= '\000' | '\002' .. '\037' | '\041' .. '\377' SPC ::= '\040' X-MSG ::= | X-N-AS+ | X-N-AS+ SPC X-CHR* 注:ここでは'+'は"一つ以上の前の文字集合"を、'*'は"0個以上の前の文字集合" を表現するために使用しています。 最初のSPCまでの文字(SPCが無い場合、X-MSGのすべて)を、拡張メッセージのタ グと呼びます。タグは拡張データの利用法を示しています。 タグは*全ての*文字列でありえますし、その中の英文字は大文字と小文字を区別し ます。 拡張データは、PRIVMSGとNOTICEコマンドでのみ有効になります。拡張データが問 い合わせへの返答の時にはNOTICEで送られますが、そうでなければPRIVMSGで送ら れます。ユーザー、またはチャンネルへのPRIVMSGとNOTICEは拡張データを含めら れます。 PRIVMSGとNOTICEのテキスト部分には、拡張メッセージでない0個以上の塊と、0 個以上の拡張メッセージを混ぜ合わせることができます。 ************************ CTCPレベルクォーティング ************************ 拡張データメッセージの内では、区切り文字X-DELIMを送れるようにこれをクォー トしなければなりません。このために別のクォート文字(再びクォートするため、 低レベルのクォート文字とは異なります)を導入します。 X-QUOTE ::='\134' (円マーク'\' ASCIIではバックスラッシュ). CTCPレベルでクォートする場合、実際のCTCPメッセージ(拡張データ、問い合わせ、 返答)だけがクォートされます。これでユーザーは、X-QUOTE文字を送ることがで きるようになります。次の変換を使用してください: X-DELIM --> X-QUOTE 'a' X-QUOTE --> X-QUOTE X-QUOTE また、CTCPレベルでデクォートする場合、CTCPメッセージは次の表の場合だけ変換 されます。 X-QUOTE 'a' --> X-DELIM X-QUOTE X-QUOTE --> X-QUOTE X-QUOTEの次に上記以外の文字が後く場合はエラーになるので、X-QUOTE文字を削っ てください。例えば、CTCPにクォートされた文字列'x'X-QUOTE'y''z'は、デクォー ト後には3文字の文字列'x''y''z'になります。 X-DELIMがCTCPメッセージの外で見つかる時には、そのメッセージはX-DELIMを含ん でいます。(この事態は、中間レベルメッセージ中に奇数個のX-DELIMがあるとき の最後のX-DELIMにのみ起こるはずです。) ****************** クォーティングの例 ****************** 3つのレベルのメッセージがあります。最高レベル(H)はユーザー−クライアン ト間のレベルのテキストです。中間の層(M)は、最高レベルメッセージにCTCP クォーティングを適用したレベルです。最低レベル(L)はクライアントからサー バーへのレベルで、中間レベルメッセージに低レベルクォーティングを適用してい ます。 低レベルのクォートをする関数lowQuote(Message)、低レベルのデクォート関数 lowDequote(Message)、CTCPレベルのクォートをする関数ctcpQuote(Message)、 CTCPレベルのデクォート関数ctcpDequote(Message)、そして全てのCTCPメッセージ を削除するctcpExtract(Message)をもちいると、次の関数の関係は真になります。 L = lowQuote(M) M = ctcpDequote(L) M = ctcpQuote(H) H = ctcpDequote(ctcpExtract(M)) 送信時に通常のテキストの中へCTCPメッセージを埋込んだ時はこうなります: M = ctcpQuote(H1) || '\001' || ctcpQuote(X) || '\001' || ctcpQuote(H2) 注:オペレーター || は文字列の連結を意味します。 もちろん、0個以上の普通のテキストメッセージと0個以上のCTCPメッセージが混合 したものがあるかもしれません。 - --- 例 1 ----------------------------------------------------------------- ユーザー(actorとする)が次の文字列を送りたいとき: はい!\nげんき? \K? ユーザーvictimに、つまりユーザがメッセージの行の中に改行(これはどうやって も、クライアントからクライアントの間では分かれてしまう)を入力したならば、 クライアントがコマンド中に入れ込むでしょう: PRIVMSG victim :はい!\nげんき? \K? CTCPクォート後はこうなります: PRIVMSG victim :はい!\nげんき? \\K? 低レベルクォートをすると PRIVMSG victim :はい!\020nげんき? \\K? そして、サーバーに送るときには改行が最後に付け加えられます。 ユーザーーvictimに届いたときはこうなります: :actor PRIVMSG victim :はい!\020nげんき? \\K? (\\kのところはSIS D47 ではOKのように見えます)低レベルデクォートの後では: :actor PRIVMSG victim :はい!\nげんき? \\K? CTCPデクォートの後では: :actor PRIVMSG victim :はい!\nげんき? \K? これがどのように表示されるかはクライアントで異なりますが、“はい!” と「げんき」の間を改行したものが推奨されます。 - --- 例 2 -------------------------------------------------------------------------------- actorのクライアントが"Emacs wins"という文字列を、あるキーを使ってSED暗号化 [SEDはCTCPで実装されたIRCクライアント間の単純なコード化プロトコルです。私 はそれとはなんの関係もありません--Ben]して送りたい場合、これは文字列 "\n\t\big\020\001\000\\:"になるようです。したがってクライアントはCTCPクォー ティングでこの文字列を文字列"\n\t\big\020\\a\000\\\\:"にして、中間レベルメッ セージを構築します: PRIVMSG victim :\001SED \n\t\big\020\\a\000\\\\:\001 低レベルクォートした後: PRIVMSG victim :\001SED \020n\t\big\020\020\\a\0200\\\\:\001 newlineを付加してサーバーのもとへ送られます。 victim側では文字列は: :actor PRIVMSG victim :\001SED \020n\t\big\020\020\\a\0200\\\\:\001 サーバーから受け取り次に低レベルデクォートされて: :actor PRIVMSG victim :\001SED \n\t\big\020\\a\000\\\\:\001 その後文字列"\n\t\big\020\\a\000\\\\:"が抽出されて、まず "\n\t\big\020\001\000\\:"にCTCPデクォートされ、そして同じキーを使用してSED で"Emacs wins"にデコードされるでしょう。 - --- 例 3 ----------------------------------------------------------------- ユーザーactorがユーザーvictimのUSERINFOを尋ねたいけれど、それが会話の最中 ならば、クライアントは通常のテキストメッセージの終わりにUSERINFOリクエスト を乗っけてしまうかもしれません。actorがテキストメッセージ "Say hi to Ron\n\t/actor"を発言したくて、victimにCTCPリクエスト"USERINFO" を要求するとき、 PRIVMSG victim :Say hi to Ron\n\t/actor と: USERINFO これをCTCPクォーティングすると: PRIVMSG victim :Say hi to Ron\n\t/actor と: USERINFO これを足しあわせて: PRIVMSG victim :Say hi to Ron\n\t/actor\001USERINFO\001 これを低レベルクォーティングすると: PRIVMSG victim :Say hi to Ron\020n\t/actor\001USERINFO\001 そしてサーバーに送ります。 victim側では、メッセージは: :actor PRIVMSG victim :Say hi to Ron\020n\t/actor\001USERINFO\001 が届きます。これを低レベルデクォートすると: :actor PRIVMSG victim :Say hi to Ron\n\t/actor\001USERINFO\001 そしてこれを分けて: :actor PRIVMSG victim :Say hi to Ron\n\t/actor と: USERINFO 両方をCTCPデクォートすると、メッセージには: :actor PRIVMSG victim :Say hi to Ron\n\t/actor が表示されます。一方CTCPコマンドは: USERINFO クライアントはこれに答えます。返答はこうなるかもしれません: USERINFO :CS student\n\001test\001 これをCTCPクォートして: USERINFO :CS student\n\\atest\\a そして返答としてNOTICEで送ります: NOTICE actor :\001USERINFO :CS student\n\\atest\\a\001 低レベルクォートして: NOTICE actor :\001USERINFO :CS student\020n\\atest\\a\001 その後これがvictimのサーバーに送られます。 これがactorのほうに着くと、メッセージは: :victim NOTICE actor :\001USERINFO :CS student\020n\\atest\\a\001 低レベルデクォートして: :victim NOTICE actor :\001USERINFO :CS student\n\\atest\\a\001 ここで全てのCTCP返答が抽出され、1つのCTCP返答と何もない正常なNOTICEが得ら れます: USERINFO :CS student\n\\atest\\a 残りの返答は、CTCPデクォートして: USERINFO :CS student\n\001test\001 最終的に、ユーザーactorに示されます。 **************** 既知の拡張データ **************** クライアント間で受け渡された拡張データは構造化された情報をそれらの間で受け 渡すために利用できます。今わかっている拡張データタイプは次のとおりです: ACTION - IRCで"ロールプレイング"をシミュレートする。 DCC - ファイル転送とクライアントの直接tcpチャットの接続を ネゴシエートします。 SED - クライアント間で暗号化されたメッセージを送ります。 アクション ========== これはロールプレイングゲームをシミュレートするためにIRCで「廃人」が使用し ます。アクションメッセージは下記のように見えます: \001ACTION barfs on the floor.\001 そのようなメッセージを受信したクライアントはユーザーが"行為"を実行している ような書式で表示するべきです。例えば、ユーザー"actor"がチャンネル "#twilight_zone"で上記のメッセージを送ったならば、他のユーザーのクライアン トは、次のようなメッセージを表示するでしょう。 [ACTION] actor>-#twilight_zone: barfs on the floor. チャンネルの他のユーザーは適切に感動すると推測されます。 DCC === DCCは"直接のクライアント接続(Direct Client Connection)"と言った風な意味を 表します。CTCP DCC拡張データメッセージは、クライアント間のファイル転送をネ ゴシエートしたり、2つのクライアントをIRCサーバーを使わずにtcp上でチャット 接続するネゴシエートをするために使われます。クライアントの接続は通常のIRC プロトコル以外のプロトコルを含んでいます。 複雑なので、DCCプロトコルの十分 な記述は、このドキュメントの端の付録A(Appendix A)に別に添付されています。 SED === SEDは、恐らく"単純な暗号化D何とか(Simple Encryption D??)"のような意味です。 これはクライアント間で暗号化されたメッセージを交換するためにクライアントが 使います。SEDでコード化されたメッセージは恐らく次のように見えます: \001SED encrypted-text-goes-here\001 このようなメッセージを受理するクライアントは解読した形で表示するべきです。 どなたかこれをドキュメント化して、付録B.(Appendix B.)に暗号化スキームを 追加してくれたなら素晴らしいのですが。 ************************* 既知のリクエスト/返答ペア ************************* リクエスト/返答ペアは二つのクライアント間で2段階で送られます。第1段階はリ クエストを送ることです。これは、"privmsg"コマンド(nickかチャンネルのどちら かに送られます。重要ではありませんが。)で行われます。第2段階は返答を送るこ とです。これは"notice"コマンドで行われます。既知のリクエスト/返答ペアは、 下記のコマンド用になります。 FINGER - ユーザーの姓名と空き時間(idle time)を返します。 VERSION - クライアントのバージョンとタイプ。 SOURCE - クライアントのコピーが手に入る場所。 USERINFO - ユーザーが決めた文字列(クライアントの制作者ではなく) CLIENTINFO - クライアントが知っている動的マスターインデックス。 ERRMSG - エラーで返答する必要があるとき使用します。 PING - クライアント間のIRCネットワークの遅延の測定に使われます。 TIME - 他のクライアントからローカルの日付と時間を取得します。 FINGER ====== これはユーザーの本名と、そしてたぶんユーザーのidle時間(この使用法はIRCプロ トコルの増強で廃れました)を取得するために使われます。リクエストは"privmsg" の中で、こんな風に \001FINGER\001 返事は"notice"のなかでこんな風に \001FINGER :#\001 #のところにユーザーの本名とクライアントマシンのログイン名と空き時間をX-N-AS の型で含めます。 VERSION ======= これは他のクライアントの名前とバージョンの情報を取得するために使われます。 リクエストは単に"privmsg"の中で \001VERSION\001 そして返答は \001VERSION #:#:#\001 最初の#がクライアントの名前を表示して、2番目の#がクライアントのバージョン を、3番目の#がクライアントが動いている環境を表示します。 使い方 X-N-CLN ::= '\000' .. '\071' | '\073' .. '\377' クライアント名はX-N-CLN型の文字列で"Kiwi"や"ircii"の様にしゃべり、バージョ ンは"5.2"や"2.1.5c"の様にしゃべり、環境は"GNU Emacs 18.57.19 under SunOS 4.1.1 on Sun SLC"や"Compiled with gcc -ansi under Ultrix 4.0 on VAX-11/730" の様にしゃべります。 SOURCE これはクライアントのコピーがどこで手にはいるかという情報を取得するために使 われます。 リクエストは"privmsg"の中で単に \001SOURCE\001 そして返答は無いかいくつかのCTCP返答で \001SOURCE #:#:#\001 の様に。 最後に終了マーカーを続けて \001SOURCE\001 匿名FTPでクライアントを取得することができる場合は、最初の#はインターネット ホストの名前を、2番目の#はディレクトリーの指定を、そして三番目の#はそのディ レクトリから取得できるスペースで区切ったファイルのリストが入ります。 Using X-N-SPC ::= '\000' .. '\037' | '\041' .. '\377' FTPサイトの名前は、"cs.bu.edu"や"funic.funet.fi"のような名前で与えられるこ とになっています。 ファイル名フィールドはスペースで区切られた1個以上のファイル名が続くディレ クトリ仕様です。ディレクトリ名だけ与えられるときは、クライアントのソースを 検索するときにはそのディレクトリの中の全てのファイルをコピーしてください。 ファイルがいくつか与えられるときには、そのディレクトリの中のそれらのファイ ルだけをコピーしてください。仕様はスペース以外の全ての文字を許していること に注意してください。これは次のことも許しています:例として"pub/emacs/irc"は pub/emacs/irc/の全てのファイルを取得できます。クライアントはまずユーザー"ftp" でログインして"CD pub/emacs/irc/"コマンドを与えて、"mget *"コマンドを続け てください。(もちろんバイナリーモードでプロンプトモードだと言うことに気を つけてください。)他の例として"/pub/irc Kiwi.5.2.el.Z"の時は、"CD /pub/irc" そして"get Kiwi.5.2.el.Z"でできます。 USERINFO ======== これはユーザーが設定する文字列を(クライアントによる設定ではなく)送信するた めに使われます。問い合わせは単に \001USERINFO\001 返答は \001USERINFO :#\001 #のところはクライアントのユーザーが設定した文字列の値です。 CLIENTINFO ========== これはクライアント開発者が他のクライアントハッカーにクライアントがCTCPが来 たときに確かに知っているものは何かを見せやすくする為にあります。理解できる 全てのCTCPコマンド、その型に予期される全ての引き数、クライアントから期待さ れるすべての返答の為に返答はかなり冗長な物になります。 問い合わせは"privmsg"にコロンを続けてスペースで区切られた一つ以上の単語で、 CLIENTINFO自身は、 \001CLIENTINFO\001 知ってるタグのリストを返答してください(上のタグデータのセクションを参照し てください)。これは人が読むことを意図しています。 一つの引数のときには、そのタグの使い方を表示してください。二つの引数の時に はタグのサブコマンドの使い方を表示してください。などなど。 ERRMSG ====== 知らない問い合わせがあるときにこれを返答に使ってください。そして、問い合わ せに使われるときには、エラーがなかったことと一緒にその問い合わせのテキスト をエコーバックの返答にしてください。次のような問い合わせが有れば、 \001ERRMSG #\001 #には全ての文字を含められます。返答は、 \001ERRMSG # :#\001 最初の#は問い合わせと同じ文字列に、2番目の#はエラーが起きてないことを通知 する短いテキストが入ります。 正常なERRMSG返答は、おかしな問い合わせや少しおかしな拡張データ受け取った時 に次のように送られます \001ERRMSG # :#\001 最初の#は失敗した問い合わせか拡張データの間違いが、2番目の#は"unkown quety" や"failed dectypting text"のようなどんな問題が起きたかの説明が入ります。 PING ==== PingはIRCネットワーク上のクライアント間の時間の遅れを測定するために使われ ます。Ping問い合わせはprivmsgでコード化され、次のような形式で: \001PING timestamp\001 'timestamp'は尋ねるクライアントにわかりやすい任意の形で現在の時間をコード 化します。答えるクライアントはnoticeの中でメッセージを送り返します。 \001PING timestamp\001 尋ねたクライアントは受け取ったタイムスタンプから現在の時間を引いて、IRCネッ トワーク上のクライアント間の遅延を取得することができます。 TIME ==== 時間問い合わせはもう一人のユーザーのクライアントが動いているところで今何時 か決定するために使われます。これは誰かが恐らく目が覚めているかどうか、それ がどこの時間帯の中にあるかどうか決めるのに便利になります。 時間問い合わせ 形式は: \001TIME\001 問い合わせはprivmsgの中で、クライアントはnoticeで次のような形式で返答して ください: \001TIME :human-readable-time-string\001 例えば: \001TIME :Thu Aug 11 22:52:51 1994 CST\001 **** 例 **** 次のように送ると PRIVMSG victim :\001FINGER\001 次のように帰ってきます :victim NOTICE actor :\001FINGER :Please check my USERINFO instead :Klaus Zeuge (sojge@mizar) 1 second has passed since victim gave a command last.\001 (USERINFOでチェックしてください。victimが最後にコマンドを与えてか ら1秒です) (これは単に1行です)か、なぜか :victim NOTICE actor :\001FINGER :Please check my USERINFO instead :Klaus Zeuge (sojge@mizar) 427 seconds (7 minutes and 7 seconds) have passed since victim gave a command last.\001 (USERINFOでチェックしてください。victimが最後にコマンドを与えてか ら427秒(7分7秒)です) Klaus Zeugeが怠けたの? :-) 次のように送ると PRIVMSG victim :\001CLIENTINFO\001 次のように帰ってきます :victim NOTICE actor :\001CLIENTINFO :You can request help of the commands CLIENTINFO ERRMSG FINGER USERINFO VERSION by giving an argument to CLIENTINFO.\001 (CLIENTINFOに引数を与えると、CLIENTINFO ERRMSG FINGER USERINFO VERSIONコマンドの説明をリクエストできます。) 次のように送ると PRIVMSG victim :\001CLIENTINFO CLIENTINFO\001 次のような返答が来ると思います :victim NOTICE actor :\001CLIENTINFO :CLIENTINFO with 0 arguments gives a list of known client query keywords. With 1 argument, a description of the client query keyword is returned.\001 (CLIENTINFOを引数無しだと、クライアントが知っているキーワードのリ ストを返します。1つ引数を与えると、キーワードの説明を返します) 次のように送っているあいだは PRIVMSG victim :\001clientinfo clientinfo\001 たぶんこんなのを返すでしょう。 :victim NOTICE actor :\001ERRMSG clientinfo clientinfo :Query is unknown\001 (わかりません) "clientinfo"というタグはありません。 次のように送ると PRIVMSG victim :\001CLIENTINFO ERRMSG\001 次のように帰ってきます :victim NOTICE actor :\001CLIENTINFO :ERRMSG is the given answer on seeing an unknown keyword. When seeing the keyword ERRMSG, it works like an echo.\001 (ERRMSGは知らないキーワードがあったときの答えです。ERRMSGがあれば、 エコーのように動きます。) 次のように送ると PRIVMSG victim :\001USERINFO\001 多少、感傷的に長い返答が: :victim NOTICE actor :\001USERINFO :I'm studying computer science in Uppsala, I'm male (somehow, that seems to be an important matter on IRC:-) and I speak fluent swedish, decent german, and some english.\001 (私はUppsalaで電算機科学を研究しています、私は男性です(なんだか、 IRCでは重要な問題みたいです:-)そして、私は流暢なスウェーデン語と正 調ドイツ語そして少し英語を話します。) 次のように送ると PRIVMSG victim :\001VERSION\001 次のように帰ってきます :victim NOTICE actor :\001VERSION Kiwi:5.2:GNU Emacs 18.57.19 under SunOS 4.1.1 on Sun SLC:FTP.Lysator.LiU.SE:/pub/emacs Kiwi-5.2.el.Z Kiwi.README\001 Sun SLCのSunOS 4.1.1の上で、クライアントがKiwiの5.2版で、GNU Emacs 18.57.19 でそれを動かているとこうなります。クライアントはFTP.Lysator.LiU.SEの匿名FTP でFTPコマンドの"cd /pub/emacs"を与えるとそのコピーを見つけられると主張して います。そこではKiwi-5.2.el.ZとKiwi.READMEのファイルを取得できます;ファイ ルのうち一つはそのファイルを取得したあとのビルドの方法を説明していると推測 されます。 ********************************************************************** 付録A DCCプロトコルの記述 ********************************************************************** By Troy Rollo (troy@plod.cbme.unsw.oz.au) Revised by Ben Mesander (ben@gnu.ai.mit.edu) オリジナルのDCCプロトコルの実装者のTroy Rolloは、DCCプロトコルは IRCII以外のクライアントに移される事を意図して設計しなかったそうです。しか し、DCCはIRCII以外の環境でも使われるようになりました。ksh, elisp, C そして perlで書かれたIRCクライアントにも、みんなDCCが実装されています。 なぜDCC? ======== DCCはIRC指向のプロトコルで、IRCサーバーネットワーク中での いくつか の制限を克服します。 DCCは対話のためのデータを運ぶためにクライアント間の直接TCP接続を使 用します。溢れ調整はないのでパケットはフルスピードで送れますし、サーバリン ク(やその負荷)に依存しません。それに加えてDCC接続の最初のハンドシェイクだ けがIRCネットワークを通されるので、クラックされたサーバーのオペレーターが 個人のメッセージをスパイすることを困難にします。 どのようにして? ================ DCC接続用の最初のソケットは、接続を始める(依頼する)側で作成され ます。このソケットはINADDE_ANYにバインドされたTCPソケットで、接続をlisten します。 接続を開始するクライアントは、ソケットを作成する際に、相手のクライ アントにCTCPコマンドを用いてその詳細を送ります。このコマンドは以下の形式を とります: DCC 形式 引数 アドレス ポート [サイズ] 型 - 接続型 引数 - 接続型により異なる引数 アドレス - 整数で表現された発信側のホストアドレス ポート - 発信側が接続を待つソケットのポート サイズ - 接続型が"SEND"だった場合(下を参照)、 サイズはファイルのサイズを示します 旧いIRCIIクライアントはこれを送信しなかったので、これが ない場合にも備えてください アドレス、ポートとサイズはそれぞれ符号無しlong、符号無しshort型及び符号無 しlongとしてホストバイトオーダーに変換して10進の整数に変換したASCII表現で 送ってください。 DCCプロトコルの実装はCTCP DCCメッセージ中のさらなる引数を受理する ために準備しておいてください。DCCがUNIX以外のオペレーティングシステムに実 装されるならば、転送するファイルのタイプをいくつか―テキスト、2進法、そし て恐らく他のもの−を指定する別の引き数を加えるかについて議論がありました。 追加の引き数がプロトコルに加えられる場合、そこにはそれらを無視するクライア ントが無視しないクライアントと共同で作業できる様な意味を、わかりやすく持た せてください。 次のDCC接続型が定義されています: 型 目的 引き数 CHAT 少し安全な会話を運ぶ 文字列"CHAT" SEND 受取人のもとへファイルを送る ファイル名 下のサブコマンドはIRCIIのDCCコマンドに含まれていますが、IRC経由でDCCリクエ ストを送信しないので、このドキュメントでは議論しません: TALK TALK接続を確立する 実装 ==== CHATとSEND接続タイプはテロリズムの可能性が有るので、自動的に受付け ないでください。その代わりに、これらの要望があったとユーザーに通知して、ユー ザーが受付を許せるようにしてください。 受取人には、それを検索する前にDCC SENDコマンドで提示されたファイル 名を改名する機会を与えてください。更には、提示されたファイルが既存のファイ ルを上書きしないことを保証するようにしてください。 古いIRCIIクライアントは、送信するファイルの全パスネームを送ります。 これはうっとおしいので、より新しいクライアントは、送信するファイルのファイ ル名部分だけを送ってください。 ポート番号は吟味してください。ポート番号がUNIXで予約されたポートの 範囲の中にあるときには、注意してから接続を受け付けてください。 それが、クライアントが32ビットの整数を扱えない実装言語の場合(例え ば emacs 18 elispやksh 88)は、だいたい元のPRIVMSGの中でhostnameを使えます。 下記は、クライアント(ここではUNIXシステム上のBSDソケットインター フェースの使用を仮定しています)で行われると思われる各段階です。 開始側: DCCコマンドを出します。 ソケットを作成し、それをINADDR_ANY、ポート0にバインドして、受動に (ソケットをリッスン)してください。 受信側にそのソケットのアドレスとポートを教える為に、CTCPでDCCリク エストを送ってください。(これは、サーバに接続するためのロー カルの側のソケットのアドレスを理想的に受け取れます。 これは推測上はネット上でもっとも接近しているホストのインタ ーフェースで、ゲートウエイノードの場合には結果はルーティン グホップが少ないものの一つです。)。 接続が受け付けられるまで、そのまま継続してください。 接続したら: 接続をアクセプトしてください。 元の受動ソケットを閉じてください。(訳注:リッスンしていたソケット。 他のリクエストを受け付けないために閉じます。) 新しいソケットで転送を処理してください。 受信側: CTCP DCCリクエストを受け取ります。 DCCリクエストの情報を記録して、ユーザーに通知してください。 ここでは、ユーザーがリクエストを異常終了(終了)か、受理することがで きるようにしてください。リクエストはコマンドが明示する、送信者、型、 引数か、か曖昧さが無いこれらの部分集合で受理してください。 受理するならば、TCPソケットを作成してください。 教えられたアドレスとポートで新しいソケットを接続してください。 ソケット上で転送を処理してください。 型の詳細な仕様 ============== CHAT CHAT接続間で送るデータは、プレフィックスやコマンドなしで一行ずつ送 られるべきです。CHAT接続を終了するには、1組が彼らのクライアントへ DCC CLOSEコマンドを出します。そのコマンドはソケットを閉じて、接続 していた情報は廃棄されます。 各行の終わりはnewline文字、'\n'です。 FILE データはストリームでダンプされるのではなく、パケットで送られます。 これで、FTP接続が失敗するようなところでもDCC SEND接続を保てるよう になります。パケットのサイズはクライアントで決められますが、ユーザー が設定してもかまいません。バケットを小さくすると、接続状態が悪くて もよく接続を保てます。受け取り側は各パケットのアクノレッジとして、 受信した全バイト数をネットワークバイトオーダーの4バイトの整数とし て送ってください。送り側は、受け取り側が今まで送った全てのデータが 確認できるまで送信を継続しないようにしてください。そして、送信側は 最後のバイトが受取人に確認されるまで接続を閉じないでください。 古いIRCIIクライアントはDCCを使って送信するファイルのサイズを送りま せん。そういうクライアントでは受信側が全ファイルが受理できたかどう かを伝えられないことに注意してください。送信側にはその情報がありま すが、IRCIIはそれを通知しません。通常は、ユーザーはファイルサイズ をチェックして転送を確認します。クライアントの作者はサイズ機能を使 用するようにしましょう。 さらに、テキスト翻訳に対する準備は行なわれないことに注意してくださ い。 IRCIIで使用されるオリジナルのブロックサイズは1024でした。他のクラ イアントはこれを採用しました。ですが、注意しておきますが、任意のブロックサ イズを受理する実装にしてください。現在のIRCIIはユーザーがブロックサイズを設 定することを許可しています。 --------------------------------[きりとり線]--------------------------------