# 通知設計書 8-接続要求通知

## 概要

本ドキュメントは、libuvにおける接続要求通知（uv_connection_cb）の設計を記述する。TCPサーバーやパイプサーバーに新規接続が到着した際にコールバックで通知するメカニズムについて定義する。

### 本通知の処理概要

uv_connection_cbは、uv_listen()でリッスン状態のストリーム（TCPサーバー、パイプサーバー）に新規クライアント接続が到着した際に、コールバックで通知する仕組みである。I/Oポーリングでリスニングソケットの読み取り可能（POLLIN）を検出し、accept()で新規接続を受け入れ、コールバックを実行する。

**業務上の目的・背景**：サーバーアプリケーションの基本的な要件として、クライアントからの接続要求を受け付ける必要がある。本通知は、非ブロッキングaccept()とイベントループの統合により、効率的な接続受付を実現する。EMFILE/ENFILE（ファイルディスクリプタ枯渇）時のフォールバック処理も含む。

**通知の送信タイミング**：uv_listen()でリッスン開始後、クライアントからの接続要求がOSカーネルのバックログキューに到着し、I/Oポーリングでリスニングソケットの読み取り可能が検出された時点で、uv__server_io()内でaccept()が実行され、コールバックが呼び出される。

**通知の受信者**：uv_listen()で設定されたコールバック関数（uv_connection_cb）が受信者となる。

**通知内容の概要**：コールバックにはサーバーストリームハンドル（uv_stream_t* server）とステータス（int status、0=成功）が渡される。コールバック内でuv_accept()を呼び出して実際の接続受入を完了する。

**期待されるアクション**：受信者はuv_accept()で新規クライアントストリームを受け入れ、そのストリームに対してuv_read_start()等の操作を開始する。

## 通知種別

コールバック通知（Cコールバック関数呼び出し）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（I/Oポーリング + accept()による接続受入） |
| 優先度 | 高（サーバーの接続受付は速やかに処理される） |
| リトライ | なし（EMFILE/ENFILE時はemfile_trickで対処） |

### 送信先決定ロジック

リスニングストリームのio_watcherにPOLLINイベントが発生すると、uv__server_io()が呼び出され、stream->connection_cbが実行される。

## 通知テンプレート

### コールバック関数シグネチャ

| 項目 | 内容 |
|-----|------|
| 関数型 | `typedef void (*uv_connection_cb)(uv_stream_t* server, int status)` |
| 定義場所 | `include/uv.h` 332行目 |

### コールバックパラメータ

```
server: uv_stream_t* - リスニング中のサーバーストリームハンドル
status: int - ステータス（0=成功）
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| server | サーバーストリームハンドル | io_watcher経由（container_of） | Yes |
| status | 接続ステータス | 0（成功時固定） | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 接続要求到着 | リスニングソケットのPOLLIN | uv_listen()でリッスン中 | uv__server_io()でaccept()実行後にコールバック |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| accept失敗 | accept()がエラーを返した場合、コールバックは呼ばれない（stream.c 523-524行目） |
| EMFILE/ENFILE | fd枯渇時はemfile_trick処理（stream.c 520-521行目） |
| ハンドルクローズ中 | UV_HANDLE_CLOSINGフラグ設定時（stream.c 515行目のassert） |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[クライアント接続要求] --> B[I/Oポーリング POLLIN検出]
    B --> C[uv__server_io]
    C --> D[uv__accept実行]
    D --> E{accept結果}
    E -->|成功| F[accepted_fd設定]
    E -->|EMFILE/ENFILE| G[uv__emfile_trick]
    E -->|その他エラー| H[リターン]
    F --> I[connection_cb呼び出し]
    I --> J{uv_accept()呼ばれた?}
    J -->|Yes| K[新規ストリームにfd設定]
    J -->|No| L[POLLIN監視停止]
    G --> H
    K --> M[終了]
    L --> M
```

## データベース参照・更新仕様

### 内部データ構造

| データ構造 | 用途 | 備考 |
|-----------|------|------|
| stream->connection_cb | 接続コールバック | uv_listen()で設定 |
| stream->accepted_fd | accept()で取得したfd | uv_accept()で消費、-1=未使用 |
| stream->io_watcher | I/Oウォッチャー | POLLINでリスニングソケット監視 |
| stream->queued_fds | キューイングされたfd群 | 複数接続到着時のfd管理 |
| loop->emfile_fd | EMFILE対策用予備fd | /dev/nullのfd、緊急時にクローズして空きを作る |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| EMFILE/ENFILE | プロセスのfd上限到達 | uv__emfile_trick()でemfile_fdを一時クローズしてaccept→close（stream.c 520-521行目） |
| accept失敗（その他） | ネットワークエラー等 | コールバックを呼ばずにリターン（stream.c 523-524行目） |
| UV_EINVAL | uv_listen()にクローズ中のストリームを渡す | エラーコード返却（stream.c 602-603行目） |
| UV_EINVAL | uv_accept()でaccepted_fd==-1 | UV_EAGAIN返却（stream.c 540-541行目） |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | なし |
| リトライ対象エラー | なし（次のPOLLINイベントで再処理） |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（backlogサイズに依存） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし。

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

- uv_accept()を呼ばない場合、accepted_fdが残りPOLLIN監視が停止される（バックプレッシャー）
- EMFILE対策でemfile_fdを使用するが、接続は即座にクローズされる（load shedding）

## 備考

- uv_listen()はストリーム型に応じてuv__tcp_listen()またはuv__pipe_listen()に委譲される（stream.c 600-616行目）
- uv_accept()はserver->queued_fdsから追加のfdを取り出し、複数の同時接続に対応する
- connection_cbのstatusは現在の実装では常に0（成功）で呼び出される（stream.c 527行目）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | 332行目: uv_connection_cb型定義、542行目: uv_listen()宣言、UV_STREAM_FIELDSのconnection_cb |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | stream.c | `src/unix/stream.c` | 600-620行目: uv_listen() - ストリーム型に応じた分岐 |

**主要処理フロー**:
1. **602行目**: クローズ中チェック
2. **606-607行目**: TCP→uv__tcp_listen()
3. **610-611行目**: Named Pipe→uv__pipe_listen()
4. **618行目**: 成功時にuv__handle_start()

#### Step 3: 接続受入処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | stream.c | `src/unix/stream.c` | 507-532行目: uv__server_io() - 接続到着時のI/Oコールバック |
| 3-2 | stream.c | `src/unix/stream.c` | 535-597行目: uv_accept() - 接続の受入完了 |

**主要処理フロー**:
- **518行目**: uv__accept()でfdを取得
- **520-521行目**: EMFILE/ENFILE時のemfile_trick
- **526行目**: accepted_fdにfd設定
- **527行目**: connection_cb(stream, 0)呼び出し
- **529-531行目**: uv_accept()未呼び出し時のPOLLIN停止

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

```
uv_listen(stream, backlog, cb)
    +-- uv__tcp_listen() / uv__pipe_listen()
    |       +-- listen(fd, backlog)
    |       +-- stream->connection_cb = cb
    |       +-- uv__io_start(POLLIN)
    +-- uv__handle_start()

[接続到着時]
uv__server_io()
    +-- uv__accept()
    +-- stream->accepted_fd = fd
    +-- stream->connection_cb(stream, 0)

[ユーザーコールバック内]
uv_accept(server, client)
    +-- uv__stream_open(client, accepted_fd)
    +-- server->accepted_fd = -1
    +-- uv__io_start(POLLIN)  ← 次の接続待ち再開
```

### データフロー図

```
[入力]                    [処理]                          [出力]

クライアント接続      I/Oポーリング (epoll/kqueue)
TCP connect()  ──▶  POLLIN検出（リスニングソケット）
                         │
                         ▼
                  uv__server_io()
                  uv__accept() → accepted_fd
                         │
                         ▼
                  connection_cb(server, 0) ──▶ ユーザーコールバック
                         │
                         ▼
                  [ユーザーが uv_accept() 呼出し]
                  uv__stream_open(client, fd)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | uv_connection_cb型定義、uv_listen()/uv_accept()宣言 |
| stream.c | `src/unix/stream.c` | ソース | uv_listen(), uv__server_io(), uv_accept()の実装 |
| tcp.c | `src/unix/tcp.c` | ソース | uv__tcp_listen()のTCP固有実装 |
| pipe.c | `src/unix/pipe.c` | ソース | uv__pipe_listen()のパイプ固有実装 |
| internal.h | `src/unix/internal.h` | ヘッダ | uv__server_io()等の内部関数宣言 |
