# 機能設計書 142-IPアドレス変換

## 概要

本ドキュメントは、libuvのネットワークユーティリティにおけるIPアドレス文字列からsockaddr構造体への変換機能 `uv_ip4_addr()` / `uv_ip6_addr()` の設計仕様を定義する。

### 本機能の処理概要

`uv_ip4_addr()` および `uv_ip6_addr()` は、人間が読めるIPアドレス文字列とポート番号を受け取り、ネットワーク通信に必要な `sockaddr_in` / `sockaddr_in6` 構造体に変換する関数である。

**業務上の目的・背景**：ネットワークプログラミングにおいて、IPアドレスは文字列形式（"192.168.1.1"、"::1" 等）で扱うことが多いが、ソケットAPIはバイナリ形式のsockaddr構造体を要求する。本機能は、この変換を簡潔かつクロスプラットフォームに行うためのヘルパー関数を提供する。TCP/UDPの接続先アドレス設定、バインドアドレス指定等、ネットワーク処理の基盤となる機能である。

**機能の利用シーン**：TCPクライアントの接続先アドレス設定(`uv_tcp_connect`)、TCPサーバーのバインドアドレス設定(`uv_tcp_bind`)、UDPソケットのバインド/送信先アドレス設定など、ネットワーク通信の前段処理として広く使用される。

**主要な処理内容**：
1. sockaddr構造体をゼロクリアする
2. アドレスファミリ（AF_INET/AF_INET6）とポート番号（ネットワークバイトオーダー）を設定する
3. IPアドレス文字列をバイナリ形式に変換する（`uv_inet_pton()` を内部使用）
4. IPv6の場合、ゾーンインデックス（%付きスコープID）のパースも行う

**関連システム・外部連携**：内部で `uv_inet_pton()` を呼び出す。IPv6のゾーンインデックス解決にはPOSIXの `if_nametoindex()` を使用する（Unix系）。

**権限による制御**：権限による実行可否の制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 29 | その他ユーティリティ | 主機能 | uv_ip4_addr()/uv_ip6_addr()による文字列→sockaddr変換のAPI定義 |

## 機能種別

データ変換処理（文字列→バイナリアドレス構造体変換）

## 入力仕様

### 入力パラメータ

#### uv_ip4_addr()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ip | const char* | Yes | IPv4アドレス文字列（例: "192.168.1.1"） | uv_inet_ptonによる形式検証 |
| port | int | Yes | ポート番号 | 0-65535 |
| addr | struct sockaddr_in* | Yes | 結果格納先 | NULLの場合は未定義動作 |

#### uv_ip6_addr()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ip | const char* | Yes | IPv6アドレス文字列（例: "::1"、"fe80::1%eth0"） | uv_inet_ptonによる形式検証 |
| port | int | Yes | ポート番号 | 0-65535 |
| addr | struct sockaddr_in6* | Yes | 結果格納先 | NULLの場合は未定義動作 |

### 入力データソース

呼び出し元から直接渡されるパラメータ。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | int | 成功時0、失敗時はlibuvエラーコード（UV_EINVAL等） |
| addr->sin_family / sin6_family | sa_family_t | AF_INET / AF_INET6 |
| addr->sin_port / sin6_port | in_port_t | ネットワークバイトオーダーのポート番号 |
| addr->sin_addr / sin6_addr | struct in_addr / in6_addr | バイナリ形式のIPアドレス |
| addr->sin6_scope_id | uint32_t | IPv6スコープID（ゾーンインデックス指定時のみ） |

### 出力先

呼び出し元が提供するsockaddr構造体に結果が格納される。

## 処理フロー

### 処理シーケンス

```
[uv_ip4_addr]
1. sockaddr_in構造体をゼロクリア (memset)
   └─ 全フィールドを0に初期化
2. sin_familyにAF_INETを設定
3. sin_portにhtons(port)でネットワークバイトオーダーのポート番号を設定
4. uv_inet_pton(AF_INET, ip, &addr->sin_addr.s_addr)でアドレス変換
   └─ 変換結果をそのまま返却

[uv_ip6_addr]
1. sockaddr_in6構造体をゼロクリア (memset)
2. sin6_familyにAF_INET6を設定
3. sin6_portにhtons(port)でネットワークバイトオーダーのポート番号を設定
4. ゾーンインデックス('%'文字)の確認
   ├─ '%'が存在する場合
   │   ├─ '%'より前のアドレス部分を分離
   │   ├─ '%'より後のゾーンインデックス文字列を取得
   │   └─ [Unix] if_nametoindex()でスコープIDに変換
   │   └─ [Win] atoi()でスコープIDに変換
   └─ '%'が存在しない場合はスキップ
5. uv_inet_pton(AF_INET6, ip, &addr->sin6_addr)でアドレス変換
```

### フローチャート

```mermaid
flowchart TD
    A[uv_ip6_addr 呼び出し] --> B[sockaddr_in6をゼロクリア]
    B --> C[sin6_family = AF_INET6]
    C --> D[sin6_port = htons port]
    D --> E{"'%'がipに含まれる?"}
    E -->|Yes| F[アドレス部分とゾーンインデックスを分離]
    F --> G[sin6_scope_idを設定]
    G --> H[uv_inet_pton でアドレス変換]
    E -->|No| H
    H --> I{変換成功?}
    I -->|Yes| J[0を返却]
    I -->|No| K[エラーコードを返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-142-01 | ゼロクリア初期化 | sockaddr構造体は変換前に必ずゼロクリアされる | 常時 |
| BR-142-02 | バイトオーダー変換 | ポート番号はhtons()でネットワークバイトオーダーに変換 | 常時 |
| BR-142-03 | ゾーンインデックス | IPv6で'%'以降はスコープIDとして処理される | uv_ip6_addrで'%'を含む場合 |
| BR-142-04 | 不明インターフェース無視 | ゾーンインデックスで不明なインターフェース(id=0)は暗黙的に無視 | if_nametoindexが0を返す場合 |

### 計算ロジック

ポート番号はhtons()マクロによりホストバイトオーダーからネットワークバイトオーダーに変換される。

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

該当なし（データベース操作は行わない）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EINVAL | 入力エラー | 不正なIPアドレス文字列 | 正しい形式のIPアドレスを指定する |
| UV_EAFNOSUPPORT | 非サポート | サポートされていないアドレスファミリ | IPv4/IPv6のみサポート |

### リトライ仕様

リトライは不要。入力パラメータの修正が必要。

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

該当なし。

## パフォーマンス要件

O(n)の線形時間（nはIPアドレス文字列長）。メモリアロケーションは行わない（スタック上のローカル変数のみ使用）。

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

- 入力文字列のバッファオーバーフロー防止のため、IPv6ゾーンインデックス部分は40バイトの固定バッファにコピーされる
- 不正な入力に対してはUV_EINVALが返却される

## 備考

- `SIN6_LEN` マクロが定義されている環境では `sin_len`/`sin6_len` フィールドも設定される（BSD系）
- IPv6ゾーンインデックスの処理はUnix版とWindows版で異なる（if_nametoindex vs atoi）
- 本関数はNo.144 inet変換（uv_inet_pton）に内部的に依存する

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | API宣言（L1780-1781） |

**読解のコツ**: sockaddr_in / sockaddr_in6 はPOSIX標準のネットワークアドレス構造体。libuvはこれらを直接使用する。

#### Step 2: 共通実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | uv-common.c | `src/uv-common.c` | uv_ip4_addr() / uv_ip6_addr() の実装 |

**主要処理フロー**:
1. **254-262行目**: `uv_ip4_addr()` - memsetでゼロクリア、AF_INET設定、htons(port)設定、uv_inet_ptonでアドレス変換
2. **265-297行目**: `uv_ip6_addr()` - ゼロクリア後、ゾーンインデックスの解析処理を含む。277行目で'%'文字を検索し、存在すればアドレス部分を分離（L279-285）、スコープID設定（L290-293）
3. **296行目**: uv_inet_pton(AF_INET6, ip, &addr->sin6_addr) で最終的なアドレス変換

#### Step 3: inet変換の下位層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | inet.c | `src/inet.c` | uv_inet_pton() の実装 |

**主要処理フロー**:
- **146-172行目**: `uv_inet_pton()` - AF_INETならinet_pton4()、AF_INET6ならinet_pton6()を呼び出す
- **175-211行目**: `inet_pton4()` - IPv4文字列のパース（ドット区切り10進数4オクテット）
- **214-298行目**: `inet_pton6()` - IPv6文字列のパース（コロン区切り16進数、::短縮表記対応）

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

```
uv_ip4_addr(ip, port, addr)              [公開API - src/uv-common.c L254]
    ├─ memset(addr, 0, sizeof(*addr))
    ├─ htons(port)
    └─ uv_inet_pton(AF_INET, ip, ...)    [公開API - src/inet.c L146]
         └─ inet_pton4(src, dst)          [内部関数 - src/inet.c L175]

uv_ip6_addr(ip, port, addr)              [公開API - src/uv-common.c L265]
    ├─ memset(addr, 0, sizeof(*addr))
    ├─ htons(port)
    ├─ strchr(ip, '%')                    [ゾーンインデックス検出]
    │   └─ if_nametoindex() / atoi()     [スコープID解決]
    └─ uv_inet_pton(AF_INET6, ip, ...)   [公開API - src/inet.c L146]
         └─ inet_pton6(src, dst)          [内部関数 - src/inet.c L214]
```

### データフロー図

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

ip文字列 ──────────▶ uv_ip4_addr/uv_ip6_addr ─────▶ sockaddr_in/sockaddr_in6
port番号 ──────────▶   ├─ memset(ゼロクリア)               ├─ sin_family
                       ├─ htons(port)                      ├─ sin_port
                       ├─ ゾーンインデックス解析(IPv6)      ├─ sin_addr/sin6_addr
                       └─ uv_inet_pton(アドレス変換)        └─ sin6_scope_id
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダー | API宣言 (L1780-1781) |
| uv-common.c | `src/uv-common.c` | ソース | uv_ip4_addr()/uv_ip6_addr() 実装 (L254-297) |
| inet.c | `src/inet.c` | ソース | uv_inet_pton() 実装 (L146-172) |
