# 機能設計書 33-ストリーム接続待受

## 概要

本ドキュメントは、libuvにおけるストリーム接続待受機能（uv_listen()）の設計仕様を記述する。TCPサーバーやパイプサーバーとしてクライアントからの接続を待ち受ける機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：ネットワークサーバーやプロセス間通信において、クライアントからの接続要求を受け付けることは最も基本的な機能である。uv_listen()はストリーム（TCP、名前付きパイプ）を接続待受状態にし、新たな接続が到着した際にコールバックを通じてアプリケーションに通知する。これにより、イベント駆動型のサーバーアーキテクチャを実現する。

**機能の利用シーン**：TCPサーバーの構築、Unixドメインソケットを使ったプロセス間通信サーバーの構築、Node.jsのnet.Server.listen()の内部実装として使用される。

**主要な処理内容**：
1. ストリームのクローズ中チェック
2. ストリーム型に応じた待受処理の委譲（TCP→uv__tcp_listen、パイプ→uv__pipe_listen）
3. ソケットのlisten()システムコール呼び出し
4. I/Oウォッチャーの設定（POLLINイベント監視開始）
5. ハンドルのアクティブ化

**関連システム・外部連携**：OSのlisten()システムコール、socket()システムコール（ソケットが未作成の場合）。

**権限による制御**：特になし。ただしソケットをバインドするアドレス/ポートによってはOS権限が必要。

## 関連画面

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

## 機能種別

サーバー初期化処理（接続待受設定）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| stream | uv_stream_t* | Yes | 待受対象のストリーム（TCP/パイプ） | UV_TCP, UV_NAMED_PIPEのいずれか |
| backlog | int | Yes | 保留接続キューの最大長 | OS依存の上限 |
| cb | uv_connection_cb | Yes | 新規接続通知コールバック | NULLでないこと |

### 入力データソース

アプリケーションコードからの直接呼び出し。事前にuv_tcp_bind()やuv_pipe_bind()でアドレスをバインドしておく必要がある。

## 出力仕様

### 出力データ

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

### 出力先

コールバック（uv_connection_cb）を通じてアプリケーションに新規接続の到着を通知する。

## 処理フロー

### 処理シーケンス

```
1. uv_listen()が呼ばれる
   └─ クローズ中チェック（uv__is_closing → UV_EINVAL）

2. ストリーム型に応じた処理委譲
   ├─ UV_TCP → uv__tcp_listen()
   │     ├─ delayed_errorチェック
   │     ├─ maybe_new_socket()でソケット作成（必要な場合）
   │     ├─ listen()システムコール
   │     ├─ connection_cbの設定
   │     ├─ UV_HANDLE_BOUNDフラグ設定
   │     ├─ io_watcherのコールバックをUV__SERVER_IOに設定
   │     └─ uv__io_start()でPOLLIN監視開始
   │
   └─ UV_NAMED_PIPE → uv__pipe_listen()

3. 成功時のハンドルアクティブ化
   └─ uv__handle_start()
```

### フローチャート

```mermaid
flowchart TD
    A[uv_listen 呼び出し] --> B{クローズ中?}
    B -->|Yes| C[UV_EINVAL 返却]
    B -->|No| D{ストリーム型}
    D -->|UV_TCP| E[uv__tcp_listen]
    D -->|UV_NAMED_PIPE| F[uv__pipe_listen]
    D -->|その他| G[UV_EINVAL 返却]
    E --> H{成功?}
    F --> H
    H -->|Yes| I[uv__handle_start]
    H -->|No| J[エラーコード返却]
    I --> K[0 返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-33-01 | ストリーム型制約 | TCPと名前付きパイプのみ接続待受可能 | 常時 |
| BR-33-02 | クローズ中拒否 | クローズ処理中のストリームでは待受不可 | 常時 |
| BR-33-03 | 暗黙的ソケット作成 | TCPの場合、ソケットが未作成であればAF_INETで自動作成 | TCP使用時 |

### 計算ロジック

特になし。

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

該当なし。

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

該当なし。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EINVAL | 入力エラー | クローズ中ストリーム、不正なストリーム型 | ストリームの状態を確認 |
| UV_EADDRINUSE | アドレスエラー | アドレスが既に使用中 | 別ポートを使用 |
| errno系エラー | システムエラー | listen()システムコールの失敗 | OS側の設定を確認 |

### リトライ仕様

listen()自体のリトライは通常行われない。

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

該当なし。

## パフォーマンス要件

- backlogパラメータは高トラフィック環境では適切な値を設定すること

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

- 特権ポート（1024未満）にバインドされたストリームのlistenにはroot権限が必要な場合がある

## 備考

- Unix実装とWindows実装で構造が異なる
- uv_listen()成功後、uv_accept()を使って個々の接続を受け入れる必要がある
- zOS環境では手動バインドが必要

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | **520-526行目**: UV_STREAM_FIELDSマクロ |
| 1-2 | uv.h | `include/uv.h` | **542行目**: uv_listen()のAPI宣言 |

**読解のコツ**: connection_cbはストリームの内部フィールドであり、uv_listen()で設定される。

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

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

**主要処理フロー**:
1. **602-604行目**: uv__is_closing()チェック
2. **605-616行目**: ストリーム型によるswitch分岐
3. **618-619行目**: uv__handle_start()

#### Step 3: TCP固有の待受処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | tcp.c | `src/unix/tcp.c` | **421-450行目**: uv__tcp_listen()の実装 |

**主要処理フロー**:
- **425-426行目**: delayed_errorチェック
- **436行目**: maybe_new_socket()
- **440行目**: listen()システムコール
- **443行目**: connection_cb設定
- **447行目**: io_watcherコールバック変更
- **449行目**: POLLIN監視開始

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

```
uv_listen(stream, backlog, cb)
    ├─ uv__is_closing(stream)
    ├─[UV_TCP] uv__tcp_listen(tcp, backlog, cb)
    │      ├─ maybe_new_socket(tcp, AF_INET, flags)
    │      ├─ listen(fd, backlog)
    │      ├─ uv__io_cb_set(&tcp->io_watcher, UV__SERVER_IO)
    │      └─ uv__io_start(loop, &tcp->io_watcher, POLLIN)
    ├─[UV_NAMED_PIPE] uv__pipe_listen(pipe, backlog, cb)
    └─ uv__handle_start(stream)
```

### データフロー図

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

stream, backlog  ───▶ uv_listen()                  ───▶ 0 or エラー
cb                     │
                       ├─ listen() syscall
                       └─ 接続到着時
                            └─ connection_cb(server, 0) ───▶ アプリケーション
```

### 関連ファイル一覧

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