# 機能設計書 34-接続受入

## 概要

本ドキュメントは、libuvにおける接続受入機能（uv_accept()）の設計仕様を記述する。待受中のサーバーストリームに到着した接続をクライアントハンドルに関連付ける機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：uv_listen()で接続待受状態にしたサーバーに新しいクライアントが接続すると、connection_cbが呼ばれる。その際、uv_accept()を呼び出して接続をクライアントハンドルに関連付ける必要がある。この関数はOSが受け入れたファイルディスクリプタをクライアント側のストリームハンドルにバインドし、データの読み書きが可能な状態にする。

**機能の利用シーン**：TCPサーバーでクライアント接続を受け入れる場合、パイプサーバーでプロセス間通信の接続を受け入れる場合に使用される。通常、uv_listen()のconnection_cbコールバック内で呼び出される。

**主要な処理内容**：
1. server->accepted_fdの存在確認（-1の場合はUV_EAGAIN）
2. クライアントのハンドル型に応じたストリームオープン（TCP/パイプ→uv__stream_open、UDP→uv_udp_open）
3. accepted_fdのクライアントへの移譲
4. キューイングされたFDの処理（複数接続が同時到着した場合）
5. I/O監視の再開（キューが空の場合はPOLLIN監視を再開）

**関連システム・外部連携**：OSのaccept()システムコール（libuvの内部で呼ばれ、accepted_fdに格納される）。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | ストリーム | 主機能 | uv_accept()による接続受け入れのAPI定義 |
| 35 | ネットワーク | 参照画面 | uv_accept()による接続受け入れ処理の使用例 |

## 機能種別

接続管理処理（サーバー側接続受入）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| server | uv_stream_t* | Yes | 接続待受中のサーバーストリーム | accepted_fdが-1でないこと |
| client | uv_stream_t* | Yes | 新規接続を受け入れるクライアントハンドル | UV_TCP, UV_NAMED_PIPE, UV_UDPのいずれか |

### 入力データソース

uv_listen()のconnection_cbコールバック内から呼び出される。clientは事前にuv_tcp_init()等で初期化しておく必要がある。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | int | 0: 成功、負値: エラーコード |

### 出力先

クライアントハンドルにファイルディスクリプタが関連付けられ、読み書き可能状態になる。

## 処理フロー

### 処理シーケンス

```
1. accepted_fdの存在確認
   └─ -1の場合 → UV_EAGAIN返却

2. クライアント型に応じたストリームオープン
   ├─ UV_NAMED_PIPE, UV_TCP → uv__stream_open(client, accepted_fd, READABLE|WRITABLE)
   └─ UV_UDP → uv_udp_open(client, accepted_fd)
   └─ その他 → UV_EINVAL

3. UV_HANDLE_BOUNDフラグ設定

4. キューイングFDの処理
   ├─ queued_fdsがある場合 → 次のFDをaccepted_fdに設定
   └─ queued_fdsがない場合
        ├─ accepted_fd = -1
        └─ uv__io_start()でPOLLIN監視を再開
```

### フローチャート

```mermaid
flowchart TD
    A[uv_accept 呼び出し] --> B{accepted_fd == -1?}
    B -->|Yes| C[UV_EAGAIN 返却]
    B -->|No| D{クライアント型}
    D -->|TCP/パイプ| E[uv__stream_open]
    D -->|UDP| F[uv_udp_open]
    D -->|その他| G[UV_EINVAL 返却]
    E --> H{成功?}
    F --> H
    H -->|No| I[uv__close でFDクローズ]
    H -->|Yes| J[UV_HANDLE_BOUND設定]
    I --> K[キューFD処理]
    J --> K
    K --> L{queued_fds あり?}
    L -->|Yes| M[次のFDをaccepted_fdに]
    L -->|No| N[accepted_fd = -1]
    N --> O[POLLIN監視再開]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-34-01 | ループ一致 | server->loopとclient->loopが同一であること（assertで検証） | 常時 |
| BR-34-02 | 1回の呼び出しで1接続 | connection_cbにつき1回uv_accept()を呼ぶ。呼ばないとI/O監視が停止したままになる | 常時 |
| BR-34-03 | キューイングFD | 複数接続が同時到着した場合、queued_fdsにFDがキューイングされる | 高負荷時 |
| BR-34-04 | EMFILE対策 | accept()がEMFILE/ENFILEを返した場合、emfile_fdトリックで一時的にFDを解放して再試行 | FD枯渇時 |

### 計算ロジック

特になし。

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

該当なし。

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

該当なし。

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EAGAIN | 一時エラー | accepted_fdが-1（受け入れ可能な接続がない） | connection_cbを待つ |
| UV_EINVAL | 入力エラー | 不正なクライアントハンドル型 | 正しいハンドル型を使用 |

### リトライ仕様

UV_EAGAINの場合、次のconnection_cb呼び出しを待てばよい。

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

該当なし。

## パフォーマンス要件

- connection_cb内で速やかにuv_accept()を呼ぶことで、次の接続受入を迅速に行える
- queued_fdsメカニズムにより、複数接続の同時到着にも対応

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

- 受け入れた接続のクライアントアドレスを検証する場合はuv_tcp_getpeername()等を使用すること

## 備考

- Unix実装ではaccepted_fdフィールドを使い、Windows実装ではハンドル型ごとに別の受入関数（uv__tcp_accept、uv__pipe_accept）に委譲する
- connection_cbが呼ばれた後にuv_accept()を呼ばないと、次の接続を受け付けるためのPOLLIN監視が再開されない

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | **543行目**: uv_accept()のAPI宣言 |

**読解のコツ**: accepted_fdはストリームの内部フィールドで、OSがaccept()で返したFDが格納される。queued_fdsは複数FDが同時到着した場合のキュー。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | stream.c | `src/unix/stream.c` | **535-597行目**: uv_accept()のUnix実装 |

**主要処理フロー**:
1. **538行目**: server->loopとclient->loopの一致をassert
2. **540-541行目**: accepted_fd == -1の場合UV_EAGAIN
3. **543-566行目**: クライアント型に応じたswitch分岐
4. **546-548行目**: TCP/パイプの場合、uv__stream_open()でREADABLE|WRITABLEフラグ付きオープン
5. **568行目**: UV_HANDLE_BOUNDフラグ設定
6. **572-595行目**: queued_fdsの処理とPOLLIN監視再開

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

```
uv_accept(server, client)
    ├─ accepted_fdチェック
    ├─[UV_TCP/UV_NAMED_PIPE] uv__stream_open(client, accepted_fd, flags)
    ├─[UV_UDP] uv_udp_open(client, accepted_fd)
    ├─ queued_fds処理
    └─ uv__io_start(loop, &server->io_watcher, POLLIN)
```

### データフロー図

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

server(accepted_fd) ───▶ uv_accept()               ───▶ client(FD関連付け済み)
client(未接続)              │                              0 or エラー
                           ├─ uv__stream_open()
                           ├─ queued_fds処理
                           └─ POLLIN監視再開
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | uv_accept()のAPI宣言 |
| stream.c | `src/unix/stream.c` | ソース | Unix版uv_accept()の実装 |
| stream.c | `src/win/stream.c` | ソース | Windows版uv_accept()の実装 |
| tcp.c | `src/win/tcp.c` | ソース | uv__tcp_accept()のWindows実装 |
