第1章:IRC入門

はじめに

IRC(Internet Relay Chat)は、1988年に誕生したリアルタイムテキスト通信プロトコルです。ft_ircでは、RFC 1459に準拠したIRCサーバーをC++で実装します。

---

1. IRCの歴史

1.1 Jarkko Oikarinenの発明

1988年夏、フィンランド:
Jarkko Oikarinen(通称WiZ)は、
フィンランドのオウル大学で働いていました。

彼は既存のMUTプログラム(チャットシステム)の
代替を開発することにしました。

最初のIRCサーバー:
- ホスト: tolsun.oulu.fi
- ポート: 6667(今日でも標準)
- 1988年8月運用開始

1.2 IRCの発展

年表:
1988: 最初のIRCサーバー(フィンランド)
1989: IRCが世界に広がり始める
1991: 湾岸戦争中、IRCでリアルタイムニュース
1993: EFnet(最初の大規模IRCネットワーク)分裂
1996: RFC 1459「Internet Relay Chat Protocol」
2000: RFC 2810-2813(IRCプロトコルの更新)
2003: IRCピーク時(100万以上の同時接続)

現在:
- Liberaチャット(Freenodeの後継)
- OFTCなどのオープンソースコミュニティ

1.3 IRCの特徴

IRCの設計思想:
1. 分散型: 複数サーバーがネットワークを形成
2. テキストベース: シンプルなプロトコル
3. リアルタイム: 低遅延通信
4. チャンネル: グループ会話
5. プライベートメッセージ: 1対1通信

      +--------+     +--------+
      |Server A|-----|Server B|
      +--------+     +--------+
        /   \           |
   +---+   +---+     +---+
   |C1 |   |C2 |     |C3 |
   +---+   +---+     +---+
   Clients

---

2. IRCの基本概念

2.1 ネットワーク構造

IRCネットワーク:
+--------+           +--------+
|Server 1|-----------|Server 2|
+--------+           +--------+
    |                     |
+--------+           +--------+
|Server 3|           |Server 4|
+--------+           +--------+

サーバー間:
- スパニングツリー構造
- ループなし(1つのパス)

ft_ircでは:
- 単一サーバーのみ実装
- サーバー間通信は不要

2.2 ユーザー識別

ニックネーム(Nickname):
- ユーザーの表示名
- ネットワーク全体で一意
- 変更可能

ユーザー名(Username):
- 接続時に設定
- 変更不可

ホストマスク:
nick!user@host
例: Alice!alice@192.168.1.100

完全識別:
:Alice!alice@192.168.1.100 PRIVMSG #channel :Hello

2.3 チャンネル

チャンネルの種類:
#channel  - 通常チャンネル(最も一般的)
&channel  - ローカルチャンネル(サーバー内のみ)

チャンネル名:
- #で始まる
- 大文字小文字を区別しない
- スペース、カンマ、^G(ASCII 7)を含まない
- 最大200文字

例:
#general
#42tokyo
#programming-help

---

3. プロジェクト概要

3.1 必須要件

ft_ircの要件:
1. C++98で実装
2. poll()(または同等)を使用
3. 非ブロッキングI/O
4. 1つのpoll()で全I/Oを処理
5. fork()禁止

対応すべきコマンド:
- PASS(パスワード認証)
- NICK(ニックネーム設定)
- USER(ユーザー登録)
- JOIN(チャンネル参加)
- PART(チャンネル退出)
- PRIVMSG(メッセージ送信)
- KICK(ユーザー追放)
- INVITE(招待)
- TOPIC(トピック設定)
- MODE(モード設定)

3.2 クラス設計

+----------+
|  Server  |
+----------+
     |
     +---> std::map<int, Client*> clients
     |
     +---> std::map<std::string, Channel*> channels
     |
     +---> poll() loop

+----------+         +----------+
|  Client  |-------->| Channel  |
+----------+         +----------+
- fd                 - name
- nickname           - topic
- username           - members
- hostname           - operators
- registered         - modes
- sendBuffer         - inviteList
- recvBuffer

3.3 ディレクトリ構造

ft_irc/
├── Makefile
├── includes/
│   ├── Server.hpp
│   ├── Client.hpp
│   ├── Channel.hpp
│   ├── Command.hpp
│   └── Utils.hpp
├── srcs/
│   ├── main.cpp
│   ├── Server.cpp
│   ├── Client.cpp
│   ├── Channel.cpp
│   ├── commands/
│   │   ├── Pass.cpp
│   │   ├── Nick.cpp
│   │   ├── User.cpp
│   │   ├── Join.cpp
│   │   ├── Part.cpp
│   │   ├── Privmsg.cpp
│   │   ├── Kick.cpp
│   │   ├── Invite.cpp
│   │   ├── Topic.cpp
│   │   └── Mode.cpp
│   └── Utils.cpp
└── conf/
    └── default.conf(オプション)

---

4. 起動とテスト

4.1 起動方法

# コンパイル
make

# 起動
./ircserv <port> <password>
./ircserv 6667 secretpass

# ポート: 1024-65535
# パスワード: 接続時に必要

4.2 テスト用IRCクライアント

# ncでテスト
nc localhost 6667

# 手動でコマンド送信
PASS secretpass
NICK Alice
USER alice 0 * :Alice Smith
JOIN #test

# irssi(CLI IRCクライアント)
irssi
/connect localhost 6667 secretpass

# WeeChat
weechat
/server add local localhost/6667 -password=secretpass
/connect local

# HexChat(GUI)
- サーバー設定でlocalhost:6667を追加

4.3 デバッグ方法

# 接続状態の確認
netstat -an | grep 6667
lsof -i :6667

# 通信内容の確認(別ターミナル)
tcpdump -i lo0 port 6667 -A

# Wiresharkでパケットキャプチャ
# IRCプロトコルのフィルタ: irc

---

5. プロトコルの基本

5.1 メッセージ形式

IRCメッセージ:
[:<prefix>] <command> [<params>...] [:<trailing>]\r\n

例:
PASS secretpass\r\n
NICK Alice\r\n
USER alice 0 * :Alice Smith\r\n

:Alice!alice@host PRIVMSG #channel :Hello, World!\r\n
:irc.server.net 001 Alice :Welcome to IRC\r\n

最大長: 512バイト(\r\n含む)

5.2 数値リプライ

成功/情報:
001 RPL_WELCOME       - 接続成功
002 RPL_YOURHOST      - サーバー情報
003 RPL_CREATED       - サーバー作成日
331 RPL_NOTOPIC       - トピックなし
332 RPL_TOPIC         - トピック
353 RPL_NAMREPLY      - チャンネルメンバー
366 RPL_ENDOFNAMES    - メンバーリスト終了

エラー:
401 ERR_NOSUCHNICK    - ニックが存在しない
403 ERR_NOSUCHCHANNEL - チャンネルが存在しない
433 ERR_NICKNAMEINUSE - ニックネーム使用中
461 ERR_NEEDMOREPARAMS - パラメータ不足
464 ERR_PASSWDMISMATCH - パスワード不一致

---

6. 実装の流れ

6.1 ステップバイステップ

Phase 1: 基盤
├── サーバーソケット作成
├── poll()によるイベントループ
├── クライアント接続/切断処理
└── 基本的なメッセージ受信

Phase 2: 認証
├── PASS コマンド
├── NICK コマンド
├── USER コマンド
└── 接続完了処理

Phase 3: チャンネル基本
├── JOIN コマンド
├── PART コマンド
├── PRIVMSG コマンド(チャンネル向け)
└── PRIVMSG コマンド(プライベート)

Phase 4: チャンネル管理
├── KICK コマンド
├── INVITE コマンド
├── TOPIC コマンド
└── MODE コマンド

Phase 5: 仕上げ
├── エラーハンドリング
├── 切断処理
└── テスト

6.2 参照クライアント

推奨クライアント:
1. irssi(軽量、CLIベース)
2. WeeChat(高機能、CLIベース)
3. HexChat(GUIベース)

テスト手順:
1. クライアントで接続
2. ニックネーム/ユーザー名設定
3. チャンネル参加
4. メッセージ送受信
5. オペレータコマンドテスト

---

まとめ

本章で学んだこと:

  • IRCの歴史: Jarkko Oikarinenの発明
  • 基本概念: ネットワーク、ユーザー、チャンネル
  • プロジェクト構造: クラス設計、ディレクトリ
  • 起動方法: 引数、テストクライアント
  • プロトコル基礎: メッセージ形式、リプライコード
  • 実装の流れ: フェーズごとの進め方

次章では、IRCプロトコルの詳細を学びます。