# 機能設計書 46-quic

## 概要

本ドキュメントは、Node.jsの`quic`モジュールの機能設計を記載する。QUICはUDP上で動作する次世代のトランスポートプロトコルであり、HTTP/3の基盤となる技術である。このモジュールはNode.jsにおけるQUIC接続の確立、データ転送、ストリーム管理機能を提供する。

### 本機能の処理概要

quicモジュールは、QUICプロトコルに基づいた安全かつ高速なネットワーク通信を実現する。QUICはTCP+TLSの機能を単一のプロトコルで提供し、接続確立の高速化、ヘッドオブラインブロッキングの解消、コネクションマイグレーションなどの利点を持つ。

**業務上の目的・背景**：従来のTCP+TLSベースの通信では、接続確立に複数のラウンドトリップが必要であり、パケットロス時にすべてのストリームがブロックされる問題があった。QUICはこれらの課題を解決し、特にモバイル環境やレイテンシが重要なアプリケーションで優れたパフォーマンスを発揮する。HTTP/3の基盤技術として、今後のWeb通信の標準となることが期待されている。

**機能の利用シーン**：
- HTTP/3サーバー/クライアントの実装
- リアルタイム通信アプリケーション
- モバイルアプリケーションのバックエンド通信
- 低レイテンシが要求されるゲームサーバー
- VPNやプロキシサービス

**主要な処理内容**：
1. `QuicEndpoint`: ローカルUDPポートのバインドとセッション管理
2. `QuicSession`: QUIC接続の確立と管理
3. `QuicStream`: 多重化されたストリームでのデータ転送
4. `connect()`: クライアント側からの接続開始
5. `listen()`: サーバー側での接続待機
6. データグラム送受信
7. TLSハンドシェイクと暗号化通信

**関連システム・外部連携**：
- TLS/SSL（暗号化通信）
- diagnostics_channel（診断イベント）
- C++バインディング（ngtcp2ライブラリ）

**権限による制御**：
- TLS証明書と秘密鍵の設定が必須（サーバー側）
- preopensによるファイルアクセス制限

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングに該当なし |

## 機能種別

ネットワーク通信 / トランスポートプロトコル

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| address | SocketAddress/String | Yes | 接続先/バインドアドレス | 有効なソケットアドレス |
| options.endpoint | EndpointOptions/QuicEndpoint | No | エンドポイント設定 | - |
| options.version | Number | No | QUICバージョン | - |
| options.transportParams | Object | No | トランスポートパラメータ | - |
| options.keys | KeyObject[] | Yes(server) | TLS秘密鍵 | private keyのみ |
| options.certs | ArrayBuffer[] | Yes(server) | TLS証明書 | - |
| options.servername | String | No | SNI | - |
| options.protocol | String | No | ALPN | - |
| options.cc | String | No | 輻輳制御アルゴリズム | 'reno'/'cubic'/'bbr' |

### 入力データソース

JavaScriptコード内からの直接呼び出し、ネットワークからのQUICパケット

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| QuicEndpoint | Class | UDPポートバインドを管理 |
| QuicSession | Class | QUIC接続を管理 |
| QuicStream | Class | 多重化されたストリーム |
| stats | Object | 接続統計情報 |

### 出力先

呼び出し元への戻り値、ネットワーク（QUICパケット送信）

## 処理フロー

### 処理シーケンス

```
1. エンドポイント作成
   └─ new QuicEndpoint(options) or connect/listen時に自動作成
2. サーバー: listen開始
   └─ listen(callback, options)
   └─ セッション受信コールバック設定
3. クライアント: connect開始
   └─ connect(address, options)
   └─ TLSハンドシェイク
4. セッション確立
   └─ ハンドシェイク完了
   └─ opened Promiseの解決
5. ストリーム作成/受信
   └─ createBidirectionalStream() / createUnidirectionalStream()
   └─ onstream コールバック
6. データ転送
   └─ stream.setOutbound(data)
   └─ stream.readable
7. セッション/エンドポイントクローズ
   └─ session.close() / endpoint.close()
   └─ closed Promiseの解決
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{サーバー or クライアント?}
    B -->|サーバー| C[listen callback, options]
    B -->|クライアント| D[connect address, options]
    C --> E[QuicEndpoint作成]
    D --> E
    E --> F[UDPバインド]
    F --> G{接続要求}
    G -->|受信| H[QuicSession作成]
    G -->|送信| H
    H --> I[TLSハンドシェイク]
    I --> J{成功?}
    J -->|No| K[エラー]
    J -->|Yes| L[session.opened解決]
    L --> M{ストリーム作成?}
    M -->|Yes| N[QuicStream作成]
    M -->|受信| O[onstream callback]
    N --> P[データ送受信]
    O --> P
    P --> Q{継続?}
    Q -->|Yes| M
    Q -->|No| R[session.close]
    R --> S[endpoint.close]
    S --> T[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 実験的機能 | --experimental-quicフラグが必要 | 常時 |
| BR-02 | TLS必須 | サーバーはkeys/certsが必須 | listen時 |
| BR-03 | ストリーム多重化 | 1セッションで複数ストリーム | 常時 |
| BR-04 | 輻輳制御 | RENO/CUBIC/BBRから選択可能 | セッションオプション |
| BR-05 | 診断チャンネル | quic.*チャンネルでイベント発行 | 常時 |

### 計算ロジック

- RTT（Round Trip Time）の測定と平滑化
- 輻輳ウィンドウ（cwnd）の管理
- パケットロスの検出とリカバリ

## データベース操作仕様

### 操作別データベース影響一覧

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ERR_QUIC_CONNECTION_FAILED | 接続エラー | 接続確立失敗 | アドレス/設定の確認 |
| ERR_QUIC_ENDPOINT_CLOSED | 状態エラー | 閉じたエンドポイントでの操作 | 新しいエンドポイント作成 |
| ERR_QUIC_OPEN_STREAM_FAILED | ストリームエラー | ストリーム作成失敗 | セッション状態の確認 |
| ERR_QUIC_TRANSPORT_ERROR | トランスポートエラー | QUICプロトコルエラー | エラーコード確認 |
| ERR_QUIC_APPLICATION_ERROR | アプリケーションエラー | アプリケーション層エラー | エラーコード確認 |
| ERR_QUIC_VERSION_NEGOTIATION_ERROR | バージョンエラー | バージョン不一致 | サポートバージョン確認 |

### リトライ仕様

- 接続エラー時は新しいセッションで再試行
- QUICプロトコルレベルでのパケット再送は自動

## トランザクション仕様

該当なし（ストリームベースの通信）

## パフォーマンス要件

- 0-RTT接続確立（セッションチケット使用時）
- マルチストリームによる並列転送
- 輻輳制御による帯域幅の効率的利用

## セキュリティ考慮事項

- **実験的機能**：セキュリティレビューが完了していない可能性
- **TLS 1.3必須**：QUIC接続は常に暗号化
- **証明書検証**：クライアント側でのサーバー証明書検証
- **クライアント検証**：verifyClientオプションでの相互認証

## 備考

- 実験的機能のため、`--experimental-quic`フラグが必要
- process.features.quicでQUICサポートを確認可能
- HTTP/3のベースとなるトランスポート層

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

quicモジュールのエントリーポイントと定数定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | quic.js | `lib/quic.js` | 1-11行目の実験的警告 |
| 1-2 | quic.js | `lib/quic.js` | 13-24行目のインポート |
| 1-3 | quic.js | `lib/quic.js` | 26-48行目の定数定義 |

**読解のコツ**: `getEnumerableConstant`ヘルパー関数が定数プロパティの定義に使用されている。cc（輻輳制御）定数として`RENO`、`CUBIC`、`BBR`が定義されていることを把握する。

#### Step 2: エントリーポイントを理解する

公開APIの定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | quic.js | `lib/quic.js` | 50-58行目のmodule.exports |

**主要処理フロー**:
1. **52行目**: `connect` - クライアント接続開始
2. **53行目**: `listen` - サーバー待機開始
3. **54行目**: `QuicEndpoint` - エンドポイントクラス
4. **55行目**: `QuicSession` - セッションクラス
5. **56行目**: `QuicStream` - ストリームクラス
6. **57行目**: `constants` - 定数オブジェクト

#### Step 3: 内部実装を理解する

internal/quic/quic.jsの主要クラスを読む。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | quic.js | `lib/internal/quic/quic.js` | 589-984行目のQuicStreamクラス |
| 3-2 | quic.js | `lib/internal/quic/quic.js` | 986-1595行目のQuicSessionクラス |
| 3-3 | quic.js | `lib/internal/quic/quic.js` | 1601-2074行目のQuicEndpointクラス |

**主要処理フロー**:
- **QuicStream**: ストリームのID、方向、読み取り/書き込み処理
- **QuicSession**: 接続管理、ストリーム作成、データグラム送受信
- **QuicEndpoint**: UDPバインド、セッション管理、接続待機/開始

#### Step 4: connect/listen関数を理解する

クライアント/サーバーの接続処理を読む。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | quic.js | `lib/internal/quic/quic.js` | 2284-2300行目のlisten関数 |
| 4-2 | quic.js | `lib/internal/quic/quic.js` | 2307-2336行目のconnect関数 |

**主要処理フロー**:
- **listen**: セッションオプション処理、endpoint[kListen]呼び出し
- **connect**: アドレス解析、セッションオプション処理、endpoint[kConnect]呼び出し

#### Step 5: 状態管理を理解する

QuicEndpointState、QuicSessionState、QuicStreamStateを読む。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | state.js | `lib/internal/quic/state.js` | 125-230行目のQuicEndpointState |
| 5-2 | state.js | `lib/internal/quic/state.js` | 232-422行目のQuicSessionState |
| 5-3 | state.js | `lib/internal/quic/state.js` | 424-608行目のQuicStreamState |

**読解のコツ**: 状態はDataViewを使ってC++側とArrayBufferを共有することで効率的に管理されている。

#### Step 6: 統計情報を理解する

QuicEndpointStats、QuicSessionStats、QuicStreamStatsを読む。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | stats.js | `lib/internal/quic/stats.js` | 145-301行目のQuicEndpointStats |
| 6-2 | stats.js | `lib/internal/quic/stats.js` | 303-533行目のQuicSessionStats |
| 6-3 | stats.js | `lib/internal/quic/stats.js` | 535-677行目のQuicStreamStats |

**読解のコツ**: 統計はBigUint64Arrayで管理され、バイト送受信量、RTT、輻輳ウィンドウなどの情報を提供する。

### プログラム呼び出し階層図

```
require('node:quic')
    │
    └─ lib/quic.js
           │
           ├─ internal/quic/quic.js
           │      │
           │      ├─ connect(address, options)
           │      │      ├─ processSessionOptions()
           │      │      ├─ processEndpointOption()
           │      │      └─ endpoint[kConnect]()
           │      │             └─ new QuicSession()
           │      │
           │      ├─ listen(callback, options)
           │      │      ├─ processSessionOptions()
           │      │      └─ endpoint[kListen]()
           │      │
           │      ├─ QuicEndpoint
           │      │      ├─ constructor()
           │      │      │      └─ new Endpoint_() // C++
           │      │      ├─ [kListen]()
           │      │      ├─ [kConnect]()
           │      │      ├─ close()
           │      │      └─ destroy()
           │      │
           │      ├─ QuicSession
           │      │      ├─ createBidirectionalStream()
           │      │      ├─ createUnidirectionalStream()
           │      │      ├─ sendDatagram()
           │      │      ├─ updateKey()
           │      │      ├─ close()
           │      │      └─ destroy()
           │      │
           │      └─ QuicStream
           │             ├─ readable
           │             ├─ setOutbound()
           │             ├─ stopSending()
           │             └─ resetStream()
           │
           ├─ internal/quic/state.js
           │      ├─ QuicEndpointState
           │      ├─ QuicSessionState
           │      └─ QuicStreamState
           │
           ├─ internal/quic/stats.js
           │      ├─ QuicEndpointStats
           │      ├─ QuicSessionStats
           │      └─ QuicStreamStats
           │
           └─ internal/quic/symbols.js
                  └─ 内部シンボル定義
```

### データフロー図

```
[クライアント]                  [サーバー]

connect(address, options)       listen(callback, options)
    │                               │
    ▼                               ▼
QuicEndpoint                   QuicEndpoint
    │                               │
    │  ◀──── QUICハンドシェイク ────▶  │
    │                               │
    ▼                               ▼
QuicSession                    QuicSession
    │                               │
    │  ◀──── ストリーム多重化 ─────▶  │
    │                               │
    ▼                               ▼
QuicStream                     QuicStream
    │                               │
    │  ◀──── 双方向データ転送 ────▶  │
    │                               │
setOutbound(data) ───────────▶ readable
readable ◀───────────────────── setOutbound(data)

[診断チャンネル]
    │
    ├─ quic.endpoint.created
    ├─ quic.endpoint.listen
    ├─ quic.session.created.*
    ├─ quic.session.handshake
    ├─ quic.session.open.stream
    ├─ quic.session.received.stream
    └─ quic.session.closed
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| quic.js | `lib/quic.js` | ソース | QUICモジュールのエントリーポイント |
| quic.js | `lib/internal/quic/quic.js` | ソース | QuicEndpoint/Session/Streamの主要実装 |
| state.js | `lib/internal/quic/state.js` | ソース | 状態管理クラス |
| stats.js | `lib/internal/quic/stats.js` | ソース | 統計情報クラス |
| symbols.js | `lib/internal/quic/symbols.js` | ソース | 内部シンボル定義 |
| socketaddress.js | `lib/internal/socketaddress.js` | ソース | SocketAddressクラス |
| validators.js | `lib/internal/validators.js` | ソース | 入力バリデーション |
| errors.js | `lib/internal/errors.js` | ソース | エラーコード定義 |
