# 機能設計書 39-TCP初期化

## 概要

本ドキュメントは、libuvにおけるTCPハンドル初期化機能（uv_tcp_init()/uv_tcp_init_ex()）の設計仕様を記述する。TCPストリームハンドルを初期化し、イベントループに登録する機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：TCPによるネットワーク通信を行うために、まずTCPハンドルを初期化する必要がある。uv_tcp_init()はデフォルト設定でハンドルを初期化し、uv_tcp_init_ex()はアドレスファミリ（AF_INET/AF_INET6）を指定してソケットの事前作成を可能にする。遅延ソケット作成により、実際にバインドや接続を行うまでアドレスファミリの決定を先延ばしにできる。

**機能の利用シーン**：TCPサーバー/クライアントの構築時に最初に呼び出す関数。すべてのTCP操作（バインド、接続、listen等）に先立って実行する必要がある。

**主要な処理内容**：
1. ストリーム基底の初期化（uv__stream_init）
2. アドレスファミリのバリデーション（AF_INET/AF_INET6/AF_UNSPEC）
3. AF_UNSPECでない場合、ソケットの即時作成（new_socket）
4. イベントループへのハンドル登録

**関連システム・外部連携**：OSのsocket()システムコール（AF_UNSPECでない場合）。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 18 | TCP | 主機能 | uv_tcp_init()/uv_tcp_init_ex()によるTCPハンドル初期化のAPI定義 |
| 3 | APIドキュメント一覧 | 遷移先機能 | TCPリファレンスページへのリンク |
| 35 | ネットワーク | 参照画面 | TCPエコーサーバーサンプルでのTCPハンドル初期化 |

## 機能種別

初期化処理

## 入力仕様

### 入力パラメータ

#### uv_tcp_init()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| loop | uv_loop_t* | Yes | イベントループ | NULLでないこと |
| handle | uv_tcp_t* | Yes | 初期化対象のTCPハンドル | NULLでないこと |

#### uv_tcp_init_ex()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| loop | uv_loop_t* | Yes | イベントループ | NULLでないこと |
| handle | uv_tcp_t* | Yes | 初期化対象のTCPハンドル | NULLでないこと |
| flags | unsigned int | Yes | 下位8ビットがアドレスファミリ | AF_INET, AF_INET6, AF_UNSPECのいずれか。上位ビットは0 |

### 入力データソース

アプリケーションコードからの直接呼び出し。

## 出力仕様

### 出力データ

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

### 出力先

TCPハンドルが初期化され、イベントループのハンドルキューに登録される。

## 処理フロー

### 処理シーケンス

```
1. uv_tcp_init()が呼ばれる
   └─ uv_tcp_init_ex(loop, tcp, AF_UNSPEC)に委譲

2. uv_tcp_init_ex()の処理
   ├─ flagsの下位8ビットからdomainを抽出
   ├─ domainのバリデーション（AF_INET/AF_INET6/AF_UNSPEC以外→UV_EINVAL）
   ├─ 上位ビットのチェック（非ゼロ→UV_EINVAL）
   ├─ uv__stream_init()でストリーム基底を初期化（UV_TCP型として登録）
   └─ AF_UNSPECでない場合
        ├─ new_socket()でソケット作成
        │     ├─ uv__socket(domain, SOCK_STREAM, 0)
        │     └─ uv__stream_open()でFDを関連付け
        └─ エラーの場合、ハンドルキューから除去しFDをクローズ
```

### フローチャート

```mermaid
flowchart TD
    A[uv_tcp_init / uv_tcp_init_ex] --> B{domain検証}
    B -->|不正| C[UV_EINVAL 返却]
    B -->|OK| D{上位ビット検証}
    D -->|非ゼロ| C
    D -->|OK| E[uv__stream_init]
    E --> F{domain == AF_UNSPEC?}
    F -->|Yes| G[0 返却（遅延ソケット作成）]
    F -->|No| H[new_socket でソケット作成]
    H --> I{成功?}
    I -->|Yes| J[0 返却]
    I -->|No| K[ハンドルキューから除去]
    K --> L[エラーコード返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-39-01 | 遅延ソケット作成 | uv_tcp_init()はAF_UNSPECで初期化するため、実際のソケットはバインドや接続時に作成される | uv_tcp_init()使用時 |
| BR-39-02 | 即時ソケット作成 | uv_tcp_init_ex()でAF_INET/AF_INET6を指定すると、初期化時にソケットが作成される | uv_tcp_init_ex()でdomain指定時 |
| BR-39-03 | flags制約 | flagsの上位ビット（8ビット以上）は0でなければならない | uv_tcp_init_ex()使用時 |
| BR-39-04 | エラー時クリーンアップ | ソケット作成に失敗した場合、ハンドルキューからの除去とFDクローズが行われる | ソケット作成失敗時 |

### 計算ロジック

`domain = flags & 0xFF` でアドレスファミリを抽出。

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

該当なし。

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

該当なし。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EINVAL | 入力エラー | 不正なアドレスファミリ、上位ビットが非ゼロ | 正しいflags値を使用 |
| UV_EMFILE | リソースエラー | FDの上限に達した（ソケット作成失敗） | ulimitを変更 |
| UV_ENOMEM | リソースエラー | メモリ不足 | メモリを解放 |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- uv_tcp_init()は遅延ソケット作成を使用するため、ソケット作成のオーバーヘッドはバインド/接続時に発生する
- uv_tcp_init_ex()でアドレスファミリを指定すると初期化時にソケットが作成されるが、後のバインド/接続でソケット再作成を回避できる

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

- 特になし。

## 備考

- uv_tcp_init()はuv_tcp_init_ex(loop, tcp, AF_UNSPEC)と等価
- new_socket()内でuv__stream_open()が呼ばれ、CLOEXEC/NONBLOCKフラグが設定される
- エラー時のクリーンアップでは、uv__stream_initで追加されたhandle_queueからの除去が行われる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | **592-596行目**: uv_tcp_s構造体の定義（UV_HANDLE_FIELDS + UV_STREAM_FIELDS + UV_TCP_PRIVATE_FIELDS） |
| 1-2 | uv.h | `include/uv.h` | **598-599行目**: uv_tcp_init()/uv_tcp_init_ex()のAPI宣言 |

**読解のコツ**: uv_tcp_tはuv_stream_tを継承し、TCP固有のプライベートフィールドを追加している。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | tcp.c | `src/unix/tcp.c` | **146-148行目**: uv_tcp_init()の実装（uv_tcp_init_exへの委譲） |
| 2-2 | tcp.c | `src/unix/tcp.c` | **113-143行目**: uv_tcp_init_ex()の実装 |

**主要処理フロー**:
1. **118行目**: `domain = flags & 0xFF` でドメイン抽出
2. **119-120行目**: ドメインバリデーション
3. **122-123行目**: 上位ビットチェック
4. **125行目**: uv__stream_init()でストリーム基底を初期化
5. **131-140行目**: AF_UNSPECでない場合のソケット作成とエラー処理

#### Step 3: ソケット作成処理を理解する

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

**主要処理フロー**:
- **68行目**: uv__socket()でSOCK_STREAMソケット作成
- **72行目**: uv__stream_open()でFDを関連付け
- **78-79行目**: UV_HANDLE_BOUNDフラグがある場合はmaybe_bind_socket()

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

```
uv_tcp_init(loop, tcp)
    └─ uv_tcp_init_ex(loop, tcp, AF_UNSPEC)
           ├─ domainバリデーション
           ├─ uv__stream_init(loop, stream, UV_TCP)
           │      └─ uv__handle_init(loop, handle, UV_TCP)
           └─[AF_UNSPEC以外] new_socket(tcp, domain, 0)
                  ├─ uv__socket(domain, SOCK_STREAM, 0)
                  └─ uv__stream_open(stream, sockfd, flags)
```

### データフロー図

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

loop, tcp, flags ───▶ uv_tcp_init_ex()             ───▶ 0 or エラー
                       │                                  tcp（初期化済み）
                       ├─ uv__stream_init()
                       │    └─ ハンドルキュー登録
                       └─ new_socket() [optional]
                              └─ socket() syscall
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | uv_tcp_t構造体とAPI宣言 |
| tcp.c | `src/unix/tcp.c` | ソース | Unix版TCP初期化実装 |
| tcp.c | `src/win/tcp.c` | ソース | Windows版TCP初期化実装 |
| stream.c | `src/unix/stream.c` | ソース | uv__stream_init()の実装 |
| uv-common.c | `src/uv-common.c` | ソース | プラットフォーム共通のuv_tcp_init/uv_tcp_bind |
