RFC2812 Internet Relay Chat: Client Protocolを読んでみた。（3.2 Channel operations）

# はじめに
どうも。こんにちは。
[42tokyo](https://42tokyo.jp/)といったところで、簡単なIRCサーバの実装を行なっています。

今回は、[3.2 Channel operations](https://datatracker.ietf.org/doc/html/rfc2812#section-3.2)を読み、チャンネル関連のコマンドについて学んで行きたいと思います。

この記事の対象範囲は以下のとおりです。
* 3.2 Channel operations
  * 3.2.1 Join message
  * 3.2.2 Part message
  * 3.2.3 Channel mode message
  * 3.2.4 Topic message
  * ~~3.2.5 Names message~~
  * ~~3.2.6 List message~~
  * 3.2.7 Invite message
  * 3.2.8 Kick command

間違い等があれば、ご指摘ください。
## 3.2 Channel operations
### 3.2.1 Join message
```
Command   : JOIN
Parameters: ( <channel> *( "," <channel> ) [ <key> *( "," <key> ) ] ) / "0"

Numeric Replies:
            461 ERR_NEEDMOREPARAMS  "<command> :Not enough parameters"
            474 ERR_BANNEDFROMCHAN  "<channel> :Cannot join channel (+b)"
            473 ERR_INVITEONLYCHAN  "<channel> :Cannot join channel (+i)"
            475 ERR_BADCHANNELKEY   "<channel> :Cannot join channel (+k)"
            471 ERR_CHANNELISFULL   "<channel> :Cannot join channel (+l)"
            476 ERR_BADCHANMASK     "<channel> :Bad Channel Mask"
            403 ERR_NOSUCHCHANNEL   "<channel name> :No such channel"
            405 ERR_TOOMANYCHANNELS "<target> :<error code> recipients. <abort message>"
            407 ERR_TOOMANYTARGETS  "<target> :<error code> recipients. <abort message>"
            437 ERR_UNAVAILRESOURCE "<nick/channel> :Nick/channel is temporarily unavailable"
            332 RPL_TOPIC           "<channel> :<topic>"

Examples:
 JOIN #foobar                ; Command to join channel #foobar.
 JOIN &foo fubar             ; Command to join channel &foo using key "fubar".
 JOIN #foo,&bar fubar        ; Command to join channel #foo using key "fubar" and &bar using no key.
 JOIN #foo,#bar fubar,foobar ; Command to join channel #foo using key "fubar", and channel #bar using key "foobar".
 JOIN #foo,#bar              ; Command to join channels #foo and #bar.
 JOIN 0                      ; Leave all currently joined channels.
 :WiZ!jto@tolsun.oulu.fi JOIN #Twilight_zone
                             ; JOIN message from WiZ on channel #Twilight_zone
```
* JOINコマンドは、ユーザがサーバに送るコマンド
* JOINコマンドは、\<channel\>へのリッスン開始をリクエストするコマンド
* サーバーは、リスト形式で渡されたパラメータを解析できなければならない **[MUST]**
* サーバは、JOINメッセージをクライアントへ送るときは、リストを使うべきではない **[SHOULD NOT]**
* サーバは、ユーザーがチャンネルに参加したとき、サーバーがチャンネルに影響を与えるすべてのコマンドに関する情報を知らせる
（コマンドには、JOIN、MODE、KICK、PART、QUIT、PRIVMSG/NOTICEが含まれる）
（これによって、チャンネルメンバーは他チャンネルのメンバーやチャンネルのモードを把握できる）
* サーバは、JOINが成功すると、ユーザに確認としてJOINメッセージを送る
* その後、チャンネルのトピック（RPL_TOPIC）と、
チャンネルに参加しているユーザのリスト（RPL_NAMREPLY）を送る
* JOINメッセージは、特別なパラメータ「"0"」を受け付けることに注意
  * これは、ユーザが現在メンバーとなっているすべてのチャネルから抜けるための特別なパラメータ
  * サーバは、ユーザが、メンバーとなっている各チャンネルに[PARTコマンド](#322-part-message)を、あたかも送信したように、このメッセージを処理する

### 3.2.2 Part message
```
   Command: PART
Parameters: <channel> *( "," <channel> ) [ <Part Message> ]
Numeric Replies:
            461 ERR_NEEDMOREPARAMS  "<command> :Not enough parameters"
            403 ERR_NOSUCHCHANNEL   "<channel name> :No such channel"
            442 ERR_NOTONCHANNEL    "<channel> :You're not on that channel"
Examples:
  PART #twilight_zone             ; Command to leave channel "#twilight_zone"
  PART #oz-ops,&group5            ; Command to leave both channels "&group5" and "#oz-ops".
  :WiZ!jto@tolsun.oulu.fi PART #playzone :I lost
                                  ; User WiZ leaving channel "#playzone" with the message "I lost".
```
* PARTコマンドは、ユーザがchannelから退出するときに使用する
* サーバは、ユーザを\<channel\>で指定されたすべてのチャンネルのアクティブメンバーリストから削除する
* \<Part Message\>がある場合、デフォルトメッセージの代わりにこのメッセージをchannelへ送信する
* デフォルトメッセージは、ニックネームであることが多い
* サーバは、このリクエストを常に許可する
* サーバは、\<channel\>をリスト形式で解析できなければならない **[MUST]**
* サーバが、クライアントにPARTメッセージを送るときはリストを使うべきではない **[SHOULD NOT]**

### 3.2.3 Channel mode message
```
   Command: MODE
Parameters: <channel> *( ( "-" / "+" ) *<modes> *<modeparams> )

Numeric Replies:
            461 ERR_NEEDMOREPARAMS   "<command> :Not enough parameters"
            467 ERR_KEYSET           "<channel> :Channel key already set"
            477 ERR_NOCHANMODES      "<channel> :Channel doesn't support modes"
            482 ERR_CHANOPRIVSNEEDED "<channel> :You're not channel operator"
            441 ERR_USERNOTINCHANNEL "<nick> <channel> :They aren't on that channel"
            472 ERR_UNKNOWNMODE      "<char> :is unknown mode char to me for <channel>"
            324 RPL_CHANNELMODEIS    "<channel> <mode> <mode params>"
            367 RPL_BANLIST          "<channel> <banmask>"
            368 RPL_ENDOFBANLIST     "<channel> :End of channel ban list"
            348 RPL_EXCEPTLIST       "<channel> <exceptionmask>"
            349 RPL_ENDOFEXCEPTLIST  "<channel> :End of channel exception list"
            346 RPL_INVITELIST       "<channel> <invitemask>"
            347 RPL_ENDOFINVITELIST  "<channel> :End of channel invite list"
            325 RPL_UNIQOPIS         "<channel> <nickname>"

Examples:
   MODE #Finnish +imI *!*@*.fi     ; Command to make #Finnish channel moderated and 'invite-only' with user with a hostname matching *.fi automatically invited.
   MODE #Finnish +o Kilroy         ; Command to give 'chanop' privileges to Kilroy on channel #Finnish.
   MODE #Finnish +v Wiz            ; Command to allow WiZ to speak on #Finnish.
   MODE #Fins -s                   ; Command to remove 'secret' flag from channel #Fins.
   MODE #42 +k oulu                ; Command to set the channel key to "oulu".
   MODE #42 -k oulu                ; Command to remove the "oulu" channel key on channel "#42".
   MODE #eu-opers +l 10            ; Command to set the limit for the number of users on channel "#eu-opers" to 10.
   :WiZ!jto@tolsun.oulu.fi MODE #eu-opers -l
                                   ; User "WiZ" removing the limit for the number of users on channel "#eu-opers".
   MODE &oulu +b                   ; Command to list ban masks set for the channel "&oulu".
   MODE &oulu +b *!*@*             ; Command to prevent all users from joining.
   MODE &oulu +b *!*@*.edu +e *!*@*.bu.edu
                                   ; Command to prevent any user from a hostname matching *.edu from joining, except if matching *.bu.edu
   MODE #bu +be *!*@*.edu *!*@*.bu.edu
                                   ; Comment to prevent any user from a hostname matching *.edu from joining, except if matching *.bu.edu
   MODE #meditation e              ; Command to list exception masks set for the channel "#meditation".
   MODE #meditation I              ; Command to list invitations masks set for the channel "#meditation".
   MODE !12345ircd O               ; Command to ask who the channel creator for "!12345ircd" is
```
* MODEコマンドは、ユーザが\<channel\>で指定したchannelの設定を照会、変更する際に使用する
使用可能なモードと用途の詳細は、[RFC2811 Internet Relay Chat Channel Management](https://datatracker.ietf.org/doc/html/rfc2811)を参照
* パラメータを取るMODEコマンドでは、１回のコマンドで、最大3つの変更が可能
* Modeコマンドの構文を理解するには、上記の「Examples:」に加え[RFC2811 Internet Relay Chat Channel Management](https://datatracker.ietf.org/doc/html/rfc2811)の定義も参照すること

### 3.2.4 Topic message

```
   Command: TOPIC
Parameters: <channel> [ <topic> ]

Numeric Replies:
            461 ERR_NEEDMOREPARAMS    "<command> :Not enough parameters"
            442 ERR_NOTONCHANNEL      "<channel> :You're not on that channel"
            331 RPL_NOTOPIC           "<channel> :No topic is set"
            332 RPL_TOPIC             "<channel> :<topic>"
            482 ERR_CHANOPRIVSNEEDED  "<channel> :You're not channel operator"
            477 ERR_NOCHANMODES       "<channel> :Channel doesn't support modes"

Examples:
   :WiZ!jto@tolsun.oulu.fi TOPIC #test :New topic
                                   ; User Wiz setting the topic.
   TOPIC #test :another topic      ; Command to set the topic on #test to "another topic".
   TOPIC #test :                   ; Command to clear the topic on #test.
   TOPIC #test                     ; Command to check the topic for #test.
```

* TOPICコマンドは、\<channel\>で指定したchannleのトピックを、変更または表示するために使用する
* \<topic\>がない場合、サーバは\<channel\>のトピックを返す
* \<topic\>がある場合、サーバは\<channel\>のトピックを変更する
* \<topic\>が空文字列の場合（上記「Examples:」を参照）、サーバは\<channel\>のトピックを削除する

### 3.2.5 Names message
```
   Command: NAMES
Parameters: [ <channel> *( "," <channel> ) [ <target> ] ]

Numerics:
                ERR_TOOMANYMATCHES
            402 ERR_NOSUCHSERVER   "<server name> :No such server"
            353 RPL_NAMREPLY       "( "=" / "*" / "@" ) <channel> :[ "@" / "+" ] <nick> *( " " [ "@" / "+" ] <nick> )
            366 RPL_ENDOFNAMES     "<channel> :End of NAMES list"

Examples:
   NAMES #twilight_zone,#42        ; Command to list visible users on #twilight_zone and #42
   NAMES                           ; Command to list all visible channels and users
```
:::note info
※今のところ、実装対象外のため省略
　参照：[RFC2812 Internet Relay Chat: Client Protocol 3.2.5 Names message](https://datatracker.ietf.org/doc/html/rfc2812#section-3.2.5)
:::

### 3.2.6 List message
```
   Command: LIST
Parameters: [ <channel> *( "," <channel> ) [ <target> ] ]
Numeric Replies:
                 ERR_TOOMANYMATCHES
             402 ERR_NOSUCHSERVER   "<server name> :No such server"
             322 RPL_LIST           "<channel> <# visible> :<topic>"
             323 RPL_LISTEND        ":End of LIST"

Examples:
   LIST                            ; Command to list all channels.
   LIST #twilight_zone,#42         ; Command to list channels #twilight_zone and #42
```
:::note info
※今のところ、実装対象外のため省略
　参照：[RFC2812 Internet Relay Chat: Client Protocol 3.2.6 List message](https://datatracker.ietf.org/doc/html/rfc2812#section-3.2.6)
:::

### 3.2.7 Invite message
```
   Command: INVITE
Parameters: <nickname> <channel>
Numeric Replies:
            461 ERR_NEEDMOREPARAMS    "<command> :Not enough parameters"
            401 ERR_NOSUCHNICK        "<nickname> :No such nick/channel"
            442 ERR_NOTONCHANNEL      "<channel> :You're not on that channel"
            443 ERR_USERONCHANNEL     "<user> <channel> :is already on channel"
            482 ERR_CHANOPRIVSNEEDED  "<channel> :You're not channel operator"
            341 RPL_INVITING          "<channel> <nick>"
            301 RPL_AWAY              "<nick> :<away message>"

Examples:
   :Angel!wings@irc.org INVITE Wiz #Dust
                                   ; Message to WiZ when he has been invited by user Angel to channel #Dust
   INVITE Wiz #Twilight_Zone       ; Command to invite WiZ to #Twilight_zone
```

* INVITEコマンドは、ユーザをchannelへ招待する際に使用
* \<nickname\>は、招待するユーザのニックネームを指定する
* \<channel\>は、存在するchannel名か、有効なchannel名である必要はない
* 存在するchannelへの招待は、そのchannelに所属するメンバだけが実行できる
* the invite-only channel flagが設定されているchannelへの招待は、Channel operatorのみできる（INVITEコマンドを発行できるのは、Channel operatorだけ。）
* 招待の通知は、招待したユーザと招待されたユーザだけが受け取る
他のchannelメンバには通知されない
（これはMODEコマンドによる変更とは異なる。ユーザにとってトラブルの原因になるときもある。）

### 3.2.8 Kick command
```
   Command: KICK
Parameters: <channel> *( "," <channel> ) <user> *( "," <user> ) [<comment>]

Numeric Replies:
            461 ERR_NEEDMOREPARAMS    "<command> :Not enough parameters"
            403 ERR_NOSUCHCHANNEL     "<channel name> :No such channel"
            476 ERR_BADCHANMASK       "<channel> :Bad Channel Mask"
            482 ERR_CHANOPRIVSNEEDED  "<channel> :You're not channel operator"
            441 ERR_USERNOTINCHANNEL  "<nick> <channel> :They aren't on that channel"
            442 ERR_NOTONCHANNEL      "<channel> :You're not on that channel"

Examples:
   KICK &Melbourne Matthew         ; Command to kick Matthew from &Melbourne
   KICK #Finnish John :Speaking English
                                   ; Command to kick John from #Finnish using "Speaking English" as the reason (comment).
   :WiZ!jto@tolsun.oulu.fi KICK #Finnish John
                                   ; KICK message on channel #Finnish from WiZ to remove John from channel
```

* KICKコマンドは、\<user\>を\<channel\>から強制的に退出させるために使用する
* KICKコマンドによって、\<user\>は強制的に\<channel\>からPARTしたことになる
* \<user\>には、必ず対象となる\<channel\>がなければならない **[MUST]**
* \<comment\>がある場合、デフォルトメッセージの代わりにKICKコマンドを発行したユーザのニックネームが送信される
* サーバは、複数のchannelまたはユーザを持つKICKメッセージを、クライアントに送信してはならない **[MUST NOT]**
これは、古いクライアントソフトウェアとの互換性を維持するために必要

# 12.Full Copyright Statement
> Copyright (C) The Internet Society (2000). All Rights Reserved.
> 
> This document and translations of it may be copied and furnished to others,
and derivative works that comment on or otherwise explain it
or assist in its implementation may be prepared, copied, published
and distributed, in whole or in part, without restriction of any kind,
provided that the above copyright notice and this paragraph are included on
all such copies and derivative works.
However, this document itself may not be modified in any way,
such as by removing the copyright notice or references to the Internet Society
or other Internet organizations, except as needed for the purpose of developing
Internet standards in which case the procedures for copyrights defined in
the Internet Standards process must be followed, or as required to
translate it into languages other than English.
> 
> The limited permissions granted above are perpetual and will not be revoked by
the Internet Society or its successors or assigns.
> 
> This document and the information contained herein is provided on an "AS IS" basis and
THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
> 
> Acknowledgement
> 
> Funding for the RFC Editor function is currently provided by the Internet Society.

# さいごに
だんだんと本格的に動き始めてきました。
ありがとうございました！

# 参考

https://datatracker.ietf.org/doc/html/rfc2812

https://datatracker.ietf.org/doc/html/rfc2811