RFC1459 Internet Relay Chat Protocolを読んでみた。（4.1 Connection Registration）

# はじめに
どうも。こんにちは。
[42tokyo](https://42tokyo.jp/)といったところで、簡単なIRCサーバの実装を行なっています。
前回は、[RFC1459 Internet Relay Chat Protocolを読んでみた。（8.Current Implementations Details）](https://qiita.com/gu-chi/items/9f0d1bdd5b812dd11d2a)を書き、IRCサーバの標準的な実装について学びました。

今回は、[RFC1459 Internet Relay Chat Protocol 4.1 Connection Registration](https://datatracker.ietf.org/doc/html/rfc1459#section-4.1)を読み、クライアントがサーバに接続してきた時に、使われるコマンドの標準的な実装について学んで行きたいと思います。

今回の記事で扱う範囲は、以下のとおりです。
* 4.Message details
  * 4.1 Connection Registration
    * 4.1.1 Password message
    * 4.1.2 Nick message
    * 4.1.3 User message

間違い等があれば、ご指摘ください。

# 4. Message details
* この章では、IRCサーバとクライアントがやりとりするメッセージについて説明する
* IRCサーバは、この章で説明するコマンドをすべて実装しなければならない。**[MUST]**
* ERR_NOSUCHSERVERは、\<server\>パラメータが見つからなかったことを意味する
* サーバは、このコマンドを受け取った場合、これ以降のレスポンスを送ってはいけない。**[MUST NOT]**
* サーバがメッセージの解析中に致命的なエラー（fatal error）が発生した場合、エラーを意味するレスポンスをクライアントに返し、解析（parse）を終了しなければならない
また、致命的なエラー以外にもエラーが発生した場合は、適切なエラーをクライアントに返す必要がある
* 致命的なエラー（fatal error）の例
  * 間違ったコマンド名
  * 知らない宛先（サーバ名、ニックネーム、チャンネル名など）
  * パラメータが足りない
  * 権限がない
  など
* パラメータの検証（validate）を行い、適切なレスポンスを返さなければならない **[MUST]**
* パラメータ・リストを使用するメッセージの場合、各パラメータに対してリプライを送らなければならない **[MUST]**
パラメータ・リストとは、カンマを区切り文字として複数のパラメータを並べる書き方のこと

```shell:メッセージの形式例
:Name COMMAND parameter list
```

## 4.1 Connection Registration
* この節で説明するコマンドは、ユーザ＝サーバ間、サーバ＝サーバ間の接続処理、登録処理、切断処理に使用される
* PASSコマンドは、接続処理や登録処理に必要ない（クライアントとサーバ共に）が、サーバ・メッセージ（SERVERコマンド）、またはNICKコマンドとUSERコマンドが組み合わさったメッセージの前に付けるべき **[MUST]**
* すべてのサーバ接続にパスワード設定することを強く推奨する。
これによって接続処理のセキュリティ性が向上する **[RECOMMEND]**
```shell:クライアントが登録する際のコマンド順序（推奨）：
1. Pass message
2. Nick message
3. User message
```

### 4.1.1 Password message
```
Command   : PASS
Parameters: <password>

Numeric Replies:
            461 ERR_NEEDMOREPARAMS   "<command> :Not enough parameters"
            462 ERR_ALREADYREGISTRED ":You may not reregister"

example   :　PASS secretpasswordhere
```
* PASSコマンドは「connection password」を設定するために使われる
* パスワードは、接続する前に設定しておかなければならない **[MUST]**
* クライアントはNICK/USERコマンドを送信する前にPASSコマンドを送信する必要がある **[MUST]**
* サーバはSERVERコマンドの前にPASSコマンドを送信する必要がある **[MUST]**
* パスワードは、設定ファイルに書かれたものと一致しなければならない **[MUST]**
* 登録前にPASSコマンドを複数回送信することは可能だが、最後に送信されたコマンドのみ登録の対象としてパラメータが検証（validate）される。一度パスワードが登録されると変更することはできない **[MAY NOT]**

### 4.1.2 Nick message
```
Command   : NICK
Parameters: <nickname> [ <hopcount> ]

Numeric Replies:
            431	ERR_NONICKNAMEGIVEN  ":No nickname given"
            432	ERR_ERRONEUSNICKNAME "<nick> :Erroneous nickname"
            433	ERR_NICKNAMEINUSE    "<nick> :Nickname is already in use"
            436	ERR_NICKCOLLISION    "<nick> :Nickname collision KILL from <user>@<host>"
            437	ERR_UNAVAILRESOURCE  "<nick/channel> :Nick/channel is temporarily unavailable"
            484	ERR_RESTRICTED       ":Your connection is restricted!"

example   : NICK Wiz                       ; ニックネームを「Wiz」で登録する。
          : WiZ NICK Kilroy                ; ニックネーム「WiZ」を「Kilroy」に変更する。
```
* NICKコマンドは、ユーザのニックネームを設定、変更するためのコマンド
* \<hopcount\>パラメータは、ニックネームとホームサーバの距離を示すもの
サーバだけが使用する
* ローカル接続の\<hopcount\>パラメータは「0」
* クライアントが\<hopcount\>パラメータを指定してもサーバは無視する。**[MUST]**
* ニックネームの衝突が発生した場合、KILLコマンドを使用して衝突したニックネームを削除する
* ニックネームの変更時に衝突が発生した場合には、変更前のニックネームも削除する **[MUST]**
* ローカル接続しているクライアントから送られてきたNICKメッセージと、
そのサーバが管理するニックネームとの間で衝突が発生した場合、
サーバは、NICKメッセージに対してERR_NICKCOLLISIONを返し、メッセージを破棄する
このとき、KILLコマンドは発行しない

### 4.1.3 User message
```
Command   : USER
Parameters: <username> <hostname> <servername> <realname>

Numeric Replies:
            461	ERR_NEEDMOREPARAMS   "<command> :Not enough parameters"
            462	ERR_ALREADYREGISTRED ":Unauthorized command (already registered)"

examples  : USER guest tolmoon tolsun :Ronnie Reagan
          ; User registering themselves with a username of "guest" and real name "Ronnie Reagan".
          :testnick USER guest tolmoon tolsun :Ronnie Reagan
          ; message between servers with the nickname for which the USER command belongs to
```
* ユーザの登録は、クライアントからUSERメッセージとNICKメッセージの両方を受け取ることで行われる
* USERコマンドは、クライアントが初めてサーバに接続するとき、各パラメータを指定するために使用される
* 新規ユーザが来たことをネットワーク中へ示すために、USERコマンドは、サーバ間の通信でも使用される
* サーバ間の通信でUSERコマンドを使用するときは、prefixとしてクライアントのニックネームを付けなければならない　**[MUST]**
* そのためサーバは、USERメッセージを送信する前に、必ずNICKメッセージを送信しなければならない **[MUST]**
* \<hostname\>パラメータと\<servername\>パラメータは、サーバー間の通信で実行されるUSERコマンドに用いられる。通常、ローカルクライアントとサーバ間の通信では使用されない
* realnameパラメータは、書式が特殊なためパラメータの最後尾に書かなければならない
* realnameパラメータは、スペース文字を含むことができ、prefixにコロン(':')を付ける
* クライアントは「Identity Server」を使用してユーザ名を設定することを推奨する

# 最後に
:::note info
コマンド（command）は、「NICK」や「PASS」自身を指す言葉。
メッセージ（message）は、コマンドとパラメータを合わせた文章を指す言葉。
と解釈しました。
:::

読むのが難しかったです。
ニックネームが重複した際の挙動を理解するのに時間が掛かりました。
KILLコマンドは、実行される状況によって処理が変わるみたいです。
次回は、[RFC2812 Internet Relay Chat: Client Protocol 3.Message Details](https://datatracker.ietf.org/doc/html/rfc2812#section-3)を読み、変更箇所を把握していきたいと思います。
ありがとうございました。

# 参考
https://datatracker.ietf.org/doc/html/rfc1459

## 4.6 Miscellaneous messages

### 4.6.1 KILL message
```
Command   : KILL
Parameters: <nickname> <comment>

Numeric Replies:
           ERR_NOPRIVILEGES
           ERR_NEEDMOREPARAMS
           ERR_NOSUCHNICK
           ERR_CANTKILLSERVER

sample   : KILL David (csd.bu.edu <- tolsun.oulu.fi)
           ; Nickname collision between csd.bu.edu and tolson.oulu.fi
```
* KILLコマンドの使用例
  * サーバがローカルクライアントとの接続を切るとき
  * サーバが管理するニックネームで重複が発生した際、両方のニックネームを削除するとき
  * オペレータがあるクライアントの接続を切るとき
* \<comment\>パラメータには、KILLコマンドが生成された理由を入れる
また、KILLコマンドが通った経路（kill-path）を付与する

NOTE：
* KILLコマンドを実行できるのは、オペレータだけにすることを推奨する
（本当に理想的な状況は、オペレータも実行できずサーバだけの権限にすること）