# 機能設計書 49-UDPバインド

## 概要

本ドキュメントは、libuv の `uv_udp_bind()` APIによりUDPソケットをローカルアドレスにバインドする機能の設計を記述する。

### 本機能の処理概要

**業務上の目的・背景**：UDPサーバーが特定のアドレスとポートでデータグラムを受信するためには、ソケットをローカルアドレスにバインドする必要がある。uv_udp_bind()はIPv4/IPv6アドレスへのバインドを行い、IPv6Only、アドレス再利用（REUSEADDR）、ポート共有（REUSEPORT）、ICMPエラーレポーティング（LINUX_RECVERR）等のオプションをサポートする。

**機能の利用シーン**：UDPサーバーの起動、マルチキャストグループへの参加前のバインド、特定インターフェースへのバインド、複数プロセスでのポート共有（SO_REUSEPORT）で使用される。

**主要な処理内容**：
1. フラグのバリデーション
2. アドレスファミリの検証とaddrlenの算出
3. ソケット未作成時の自動作成（SOCK_DGRAM）
4. LINUX_RECVERR、REUSEADDR、REUSEPORTオプションの設定
5. IPv6Onlyオプションの設定
6. bind()システムコールの呼び出し
7. ハンドルフラグの更新（UV_HANDLE_BOUND, UV_HANDLE_IPV6）

**関連システム・外部連携**：OSのソケットAPI（bind(), setsockopt()）を使用する。

**権限による制御**：ウェルノウンポート（1024未満）へのバインドにはroot/管理者権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 21 | UDP | 主機能 | uv_udp_bind()によるUDPソケットバインドのAPI定義 |

## 機能種別

ネットワーク設定（ソケットバインド）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| handle | uv_udp_t* | Yes | 初期化済みUDPハンドル | handle->type == UV_UDP |
| addr | const struct sockaddr* | Yes | バインド先アドレス | sa_family == AF_INET or AF_INET6 |
| flags | unsigned int | Yes | バインドオプション | UV_UDP_IPV6ONLY, UV_UDP_REUSEADDR, UV_UDP_REUSEPORT, UV_UDP_LINUX_RECVERR の組み合わせ |

### 入力データソース

アプリケーションから直接呼び出される。アドレスはuv_ip4_addr()/uv_ip6_addr()で構築される。

## 出力仕様

### 出力データ

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

### 出力先

戻り値として直接返却。

## 処理フロー

### 処理シーケンス

```
1. 型チェック（uv-common.c）
   └─ handle->type != UV_UDP → UV_EINVAL
2. アドレスファミリチェック・addrlen算出（uv-common.c）
   └─ AF_INET/AF_INET6のみ許可
3. uv__udp_bind()呼び出し（unix/udp.c）
   ├─ フラグバリデーション（不正フラグチェック）
   ├─ IPv6Only制約チェック（IPv6以外でIPV6ONLYは不可）
   ├─ ソケット未作成時：uv__socket()で自動作成
   ├─ UV_UDP_LINUX_RECVERR: IP_RECVERR/IPV6_RECVERR設定
   ├─ UV_UDP_REUSEADDR: SO_REUSEADDR/SO_REUSEPORT(BSD)設定
   ├─ UV_UDP_REUSEPORT: SO_REUSEPORT設定
   ├─ UV_UDP_IPV6ONLY: IPV6_V6ONLY設定
   ├─ bind()システムコール
   └─ フラグ更新（UV_HANDLE_BOUND, UV_HANDLE_IPV6）
```

### フローチャート

```mermaid
flowchart TD
    A[uv_udp_bind 呼び出し] --> B{handle->type == UV_UDP?}
    B -->|No| C[UV_EINVAL返却]
    B -->|Yes| D{addr->sa_family有効?}
    D -->|No| C
    D -->|Yes| E[uv__udp_bind呼び出し]
    E --> F{フラグ有効?}
    F -->|No| C
    F -->|Yes| G{ソケット存在?}
    G -->|No| H[uv__socket作成]
    G -->|Yes| I[オプション設定]
    H --> I
    I --> J[bind システムコール]
    J --> K{成功?}
    K -->|No| L[エラー返却]
    K -->|Yes| M[フラグ更新]
    M --> N[0 を返す]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-49-1 | フラグ制限 | UV_UDP_IPV6ONLY, UV_UDP_REUSEADDR, UV_UDP_REUSEPORT, UV_UDP_LINUX_RECVERR以外のフラグは不可 | 常時 |
| BR-49-2 | IPv6Only制約 | UV_UDP_IPV6ONLYはIPv6アドレスでのバインド時のみ有効 | flags & UV_UDP_IPV6ONLY |
| BR-49-3 | ソケット自動作成 | ソケット未作成時はアドレスファミリに基づいて自動作成 | handle->io_watcher.fd == -1 |
| BR-49-4 | EAFNOSUPPORTマッピング | EAFNOSUPPORTはUV_EINVALに変換される | errno == EAFNOSUPPORT |

### 計算ロジック

特になし。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EINVAL | バリデーションエラー | ハンドル型不正、アドレスファミリ不正、不正フラグ | 正しいパラメータを指定する |
| UV_EADDRINUSE | アドレス使用中 | 指定アドレス/ポートが使用中 | 別のポートを使用するかREUSEADDR/REUSEPORTを指定する |
| UV_EACCES | 権限不足 | 特権ポートへのバインド | root権限で実行する |
| UV_ENOTSUP | 未サポート | IPV6_V6ONLY非対応プラットフォーム | IPv6Onlyフラグを外す |

### リトライ仕様

リトライは不要。

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

該当なし。

## パフォーマンス要件

同期的に完了する操作。ソケット作成を伴う場合はシステムコールのオーバーヘッドあり。

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

- ウェルノウンポートへのバインドには適切な権限が必要。
- SO_REUSEPORTの使用は、他プロセスへのパケット横取りのリスクがある。

## 備考

- BSD系ではSO_REUSEPORTがSO_REUSEADDRの機能を含むため、UV_UDP_REUSEADDRフラグでSO_REUSEPORTが設定される場合がある。
- Linux環境でUV_UDP_LINUX_RECVERRを指定すると、ICMPエラーが完全にレポートされ、DNS等でのフェイルオーバーが高速化される。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | uv_udp_flags列挙型（656-711行目）。各フラグの意味を理解する |
| 1-2 | uv.h | `include/uv.h` | uv_udp_bind()のAPI宣言（750-752行目） |

**読解のコツ**: flagsパラメータは複数のフラグをOR結合で指定する。UV_UDP_REUSEADDRとUV_UDP_REUSEPORTは似て非なるオプション。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | uv-common.c | `src/uv-common.c` | uv_udp_bind()の共通実装（375-391行目） |

**主要処理フロー**:
1. **380-381行目**: handle->type != UV_UDP チェック
2. **383-388行目**: sa_familyからaddrlenを算出
3. **390行目**: uv__udp_bind()へ委譲

#### Step 3: プラットフォーム固有実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | udp.c | `src/unix/udp.c` | uv__udp_bind()の実装（440-511行目） |
| 3-2 | udp.c | `src/unix/udp.c` | uv__sock_reuseaddr()（379-415行目）。プラットフォーム固有のアドレス再利用設定 |

**主要処理フロー**:
- **449-451行目**: 不正フラグチェック
- **454-455行目**: IPv6Only + 非IPv6の組み合わせチェック
- **457-464行目**: ソケット未作成時の自動作成
- **466-470行目**: LINUX_RECVERR設定
- **472-476行目**: REUSEADDR設定
- **478-482行目**: REUSEPORT設定
- **484-495行目**: IPv6Only設定
- **497-504行目**: bind()システムコール
- **506-509行目**: フラグ更新

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

```
uv_udp_bind() [src/uv-common.c:375]
    │
    └─ uv__udp_bind() [src/unix/udp.c:440]
           │
           ├─ uv__socket() [src/unix/core.c] (ソケット未作成時)
           │
           ├─ uv__set_recverr() [src/unix/udp.c:423]
           │
           ├─ uv__sock_reuseaddr() [src/unix/udp.c:379]
           │
           ├─ uv__sock_reuseport() [src/unix/core.c]
           │
           ├─ setsockopt(IPV6_V6ONLY) [OS]
           │
           └─ bind() [OS system call]
```

### データフロー図

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

uv_udp_t* handle         ──▶  uv_udp_bind()            ──▶  戻り値(0/エラー)
const sockaddr* addr      ──▶  ├ 型・アドレスチェック
unsigned int flags        ──▶  ├ ソケット作成(必要時)
                               ├ オプション設定
                               ├ bind()呼び出し
                               └ フラグ更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダー | API宣言、uv_udp_flags列挙型 |
| uv-common.c | `src/uv-common.c` | ソース | uv_udp_bind()共通実装 |
| udp.c (unix) | `src/unix/udp.c` | ソース | uv__udp_bind()、uv__sock_reuseaddr()等の実装 |
| udp.c (win) | `src/win/udp.c` | ソース | Windows固有のバインド実装 |
| core.c | `src/unix/core.c` | ソース | uv__socket(), uv__sock_reuseport()の実装 |
