# 機能設計書 56-マルチキャスト制御

## 概要

本ドキュメントは、libuvにおけるマルチキャストグループ制御機能（`uv_udp_set_membership()` / `uv_udp_set_source_membership()`）の設計仕様を記述する。UDPソケットのマルチキャストグループへの参加・離脱を制御する。

### 本機能の処理概要

**業務上の目的・背景**：マルチキャスト通信は、同一データを複数のホストに効率的に配信するための技術である。サービスディスカバリ（mDNS）、ストリーミング配信、リアルタイム通信プロトコルなどで広く使用される。本機能はUDPソケットのマルチキャストグループ参加・離脱を制御し、IPv4/IPv6両方に対応する。`uv_udp_set_source_membership()`はSSM（Source-Specific Multicast）をサポートする拡張版である。

**機能の利用シーン**：
- mDNSによるサービスディスカバリ
- マルチキャスト映像・音声ストリーミング受信
- IGMPv3/MLDv2ベースのSSM（ソース固有マルチキャスト）
- IoTデバイス間のグループ通信

**主要な処理内容**：
1. マルチキャストアドレスのIPv4/IPv6判定
2. 必要に応じた遅延バインド（SO_REUSEADDR付き）
3. IP_ADD_MEMBERSHIP/IP_DROP_MEMBERSHIP（IPv4）の設定
4. IPV6_ADD_MEMBERSHIP/IPV6_DROP_MEMBERSHIP（IPv6）の設定
5. SSM: IP_ADD_SOURCE_MEMBERSHIP/MCAST_JOIN_SOURCE_GROUP等の設定

**関連システム・外部連携**：OSのソケットAPI（setsockopt）、ネットワークスタック（IGMP/MLD）。

**権限による制御**：特になし。ただし一部OSではマルチキャスト操作にroot権限が必要な場合がある。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 21 | UDP | 主機能 | uv_udp_set_membership()/uv_udp_set_source_membership()のAPI定義 |

## 機能種別

ソケットオプション設定 / マルチキャスト制御

## 入力仕様

### 入力パラメータ

#### uv_udp_set_membership()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| handle | uv_udp_t* | Yes | UDPハンドル | 初期化済みであること |
| multicast_addr | const char* | Yes | マルチキャストグループアドレス | 有効なIPv4/IPv6マルチキャストアドレス |
| interface_addr | const char* | No | インターフェースアドレス | NULLの場合はデフォルトインターフェース |
| membership | uv_membership | Yes | 参加/離脱の指定 | UV_JOIN_GROUP or UV_LEAVE_GROUP |

#### uv_udp_set_source_membership()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| handle | uv_udp_t* | Yes | UDPハンドル | 初期化済みであること |
| multicast_addr | const char* | Yes | マルチキャストグループアドレス | 有効なIPv4/IPv6マルチキャストアドレス |
| interface_addr | const char* | No | インターフェースアドレス | NULLの場合はデフォルト |
| source_addr | const char* | Yes | ソースアドレス（SSM） | 有効なIPアドレス |
| membership | uv_membership | Yes | 参加/離脱 | UV_JOIN_GROUP or UV_LEAVE_GROUP |

### 入力データソース

アプリケーションから直接指定されるマルチキャストグループパラメータ。

## 出力仕様

### 出力データ

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

### 出力先

OSカーネルのソケットオプションが変更される。

## 処理フロー

### 処理シーケンス

```
[uv_udp_set_membership]
1. multicast_addrをIPv4としてパース試行
   ├─ 成功: AF_INET遅延バインド → uv__udp_set_membership4()
   └─ 失敗: IPv6としてパース試行
        ├─ 成功: AF_INET6遅延バインド → uv__udp_set_membership6()
        └─ 失敗: UV_EINVAL

[uv__udp_set_membership4]
1. interface_addrをin_addr形式に変換（NULLならINADDR_ANY）
2. ip_mreq構造体を構築
3. membershipに応じてIP_ADD_MEMBERSHIP/IP_DROP_MEMBERSHIPを選択
4. setsockopt()で設定

[uv_udp_set_source_membership]
1. multicast_addrとsource_addrをIPv4/IPv6としてパース
2. IPv4: uv__udp_set_source_membership4()
3. IPv6: uv__udp_set_source_membership6()
4. setsockopt()で設定
```

### フローチャート

```mermaid
flowchart TD
    A[uv_udp_set_membership] --> B{IPv4パース成功?}
    B -->|Yes| C[AF_INET遅延バインド]
    C --> D[uv__udp_set_membership4]
    D --> E[setsockopt IP_ADD/DROP_MEMBERSHIP]
    B -->|No| F{IPv6パース成功?}
    F -->|Yes| G[AF_INET6遅延バインド]
    G --> H[uv__udp_set_membership6]
    H --> I[setsockopt IPV6_ADD/DROP_MEMBERSHIP]
    F -->|No| J[UV_EINVAL]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-56-01 | 自動バインド | マルチキャスト参加時にUV_UDP_REUSEADDR付きで自動バインドされる | ソケット未バインド時 |
| BR-56-02 | SSMプラットフォーム制限 | set_source_membershipはOpenBSD、NetBSD、Android、DragonFlyBSD、GNU Hurdでは非サポート | 該当プラットフォーム |
| BR-56-03 | IPv4/IPv6自動判定 | マルチキャストアドレスの形式からIPv4/IPv6を自動判定する | 常時 |
| BR-56-04 | z/OS ENXIO変換 | z/OSでENXIOエラーはUV_ENODEVに変換される | z/OS環境 |

### 計算ロジック

特になし。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EINVAL | パラメータ不正 | 無効なマルチキャストアドレス / membershipが不正 | 正しいアドレスを指定 |
| UV_ENODEV | デバイスなし | z/OSでインターフェースが見つからない場合 | インターフェースを確認 |
| UV_ENOSYS | 非サポート | SSMが非対応プラットフォーム | set_membershipを使用 |

### リトライ仕様

リトライは不要。

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

該当なし。

## パフォーマンス要件

同期処理。setsockopt()の実行時間のみ。

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

- マルチキャストグループへの参加は、そのグループ宛の全てのデータを受信することを意味する
- SSMを使用することで受信ソースを制限でき、セキュリティを向上できる

## 備考

- uv_udp_set_membership()で遅延バインド時にSO_REUSEADDRが自動設定される
- IPv6のインターフェース指定はscope_idを使用する

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | **L761-769行目**: uv_udp_set_membership()/set_source_membership()のAPI宣言 |
| 1-2 | uv.h | `include/uv.h` | uv_membership列挙型（UV_JOIN_GROUP, UV_LEAVE_GROUP） |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | udp.c (unix) | `src/unix/udp.c` | **L1020-1041行目**: uv_udp_set_membership() - IPv4/IPv6判定と遅延バインド |
| 2-2 | udp.c (unix) | `src/unix/udp.c` | **L1044-1085行目**: uv_udp_set_source_membership() - SSMの実装 |

#### Step 3: IPv4/IPv6固有の実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | udp.c (unix) | `src/unix/udp.c` | **L743-787行目**: uv__udp_set_membership4() - ip_mreq構築とsetsockopt |
| 3-2 | udp.c (unix) | `src/unix/udp.c` | **L790-834行目**: uv__udp_set_membership6() - ipv6_mreq構築とsetsockopt |
| 3-3 | udp.c (unix) | `src/unix/udp.c` | **L843-885行目**: uv__udp_set_source_membership4() - SSM IPv4 |
| 3-4 | udp.c (unix) | `src/unix/udp.c` | **L888-935行目**: uv__udp_set_source_membership6() - SSM IPv6 |

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

```
uv_udp_set_membership(handle, multicast_addr, interface_addr, membership)
    ├─ uv_ip4_addr(multicast_addr, ...) [IPv4判定]
    │      ├─ uv__udp_maybe_deferred_bind(handle, AF_INET, UV_UDP_REUSEADDR)
    │      └─ uv__udp_set_membership4(handle, &addr4, interface_addr, membership)
    │             └─ setsockopt(IPPROTO_IP, IP_ADD/DROP_MEMBERSHIP)
    │
    └─ uv_ip6_addr(multicast_addr, ...) [IPv6判定]
           ├─ uv__udp_maybe_deferred_bind(handle, AF_INET6, UV_UDP_REUSEADDR)
           └─ uv__udp_set_membership6(handle, &addr6, interface_addr, membership)
                  └─ setsockopt(IPPROTO_IPV6, IPV6_ADD/DROP_MEMBERSHIP)
```

### データフロー図

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

multicast_addr ──────▶ IPv4/IPv6判定 ──────▶ setsockopt()
interface_addr              │                      │
membership                  ├─ ip_mreq構築         └─ カーネルマルチキャスト
                            └─ ipv6_mreq構築           テーブル更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | API宣言 |
| udp.c (unix) | `src/unix/udp.c` | ソース | Unix系マルチキャスト実装 |
| udp.c (win) | `src/win/udp.c` | ソース | Windows版マルチキャスト実装 |
