# 機能設計書 123-名前逆引き

## 概要

本ドキュメントは、libuvが提供するDNS名前逆引き機能 `uv_getnameinfo()` の設計仕様を記述する。ソケットアドレスからホスト名とサービス名を非同期で取得するための機能である。

### 本機能の処理概要

**業務上の目的・背景**：ネットワークプログラミングにおいて、IPアドレスからホスト名を取得するDNS逆引きは、ログ記録やアクセス制御に頻繁に使用される処理である。標準Cライブラリの `getnameinfo()` はブロッキング関数であるため、libuvはスレッドプールを利用して非同期化している。これにより、イベントループをブロックすることなくDNS逆引きを実行できる。

**機能の利用シーン**：サーバーアプリケーションで接続元クライアントのIPアドレスからホスト名を取得する場合や、ネットワーク診断ツールでIPアドレスを人間が読みやすいホスト名に変換する場合に使用される。

**主要な処理内容**：
1. 入力パラメータ（req, addr）のバリデーションとアドレスファミリの検証
2. ソケットアドレスをリクエスト構造体内のストレージにコピー
3. リクエスト初期化とフラグ設定
4. コールバックが指定された場合はスレッドプール（SLOW_IO種別）にワークを投入
5. コールバックがNULLの場合は同期実行
6. ワーカースレッド上で `getnameinfo()` システムコールを実行
7. 完了時にコールバックでホスト名とサービス名を返却

**関連システム・外部連携**：OSの `getnameinfo()` システムコールを使用する。スレッドプールシステムと連携する。エラーコード変換は `uv__getaddrinfo_translate_error()` を共用する。

**権限による制御**：特になし。DNS逆引きはOSのネットワーク設定に依存する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 26 | DNS | 主機能 | uv_getnameinfo()による非同期DNS逆引きのAPI定義 |

## 機能種別

データ連携（非同期DNS逆引き処理）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| loop | uv_loop_t* | Yes | イベントループ | - |
| req | uv_getnameinfo_t* | Yes | リクエスト構造体 | NULL不可 |
| getnameinfo_cb | uv_getnameinfo_cb | No | 完了コールバック。NULLの場合は同期実行 | - |
| addr | const struct sockaddr* | Yes | 逆引き対象のソケットアドレス | NULL不可、AF_INET/AF_INET6のみ |
| flags | int | No | getnameinfo()に渡すフラグ（NI_NAMEREQD等） | - |

### 入力データソース

ユーザーからの関数呼び出しパラメータ。addrはIPv4（struct sockaddr_in）またはIPv6（struct sockaddr_in6）のアドレスを指定する。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | int | 非同期: 0（成功）/ エラーコード、同期: retcode値 |
| host | char* | 解決されたホスト名（コールバック引数） |
| service | char* | 解決されたサービス名（コールバック引数） |

### 出力先

コールバック関数への引数として返却。host/serviceはリクエスト構造体内のバッファを指す。

## 処理フロー

### 処理シーケンス

```
1. 入力パラメータのバリデーション
   └─ req==NULL、addr==NULLの場合UV_EINVAL
2. アドレスファミリの検証とコピー
   └─ AF_INET: sockaddr_inをstorageにコピー
   └─ AF_INET6: sockaddr_in6をstorageにコピー
   └─ その他: UV_EINVAL
3. リクエスト初期化
   └─ uv__req_init()でリクエスト型UV_GETNAMEINFOを設定
   └─ コールバック、フラグ、ループ、retcodeを設定
4. ワーク投入またはインライン実行
   └─ cb != NULL: uv__work_submit()でSLOW_IOとしてスレッドプールに投入
   └─ cb == NULL: 同期的にwork/done関数を呼び出し
5. ワーカー処理
   └─ アドレスファミリに応じたsalenを計算
   └─ getnameinfo()システムコールを呼び出し
   └─ エラーコードをuv__getaddrinfo_translate_error()で変換
6. 完了処理
   └─ キャンセル時はretcodeをUV_EAI_CANCELEDに設定
   └─ コールバックを呼び出し（host, serviceを引数として）
```

### フローチャート

```mermaid
flowchart TD
    A[uv_getnameinfo呼び出し] --> B{パラメータ検証}
    B -->|不正| Z[UV_EINVAL返却]
    B -->|正常| C{アドレスファミリ?}
    C -->|AF_INET| D[sockaddr_inをコピー]
    C -->|AF_INET6| E[sockaddr_in6をコピー]
    C -->|その他| Z
    D --> F[リクエスト初期化]
    E --> F
    F --> G{cb != NULL?}
    G -->|Yes| H[uv__work_submit SLOW_IO]
    H --> I[ワーカーでgetnameinfo実行]
    I --> J[コールバック host, service]
    G -->|No| K[同期実行]
    K --> L[retcode返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-123-1 | アドレスファミリ制限 | AF_INETとAF_INET6のみ対応。それ以外はUV_EINVAL | 常時 |
| BR-123-2 | SLOW_IO分類 | DNS逆引きはSLOW_IOとしてスレッドプールに投入 | 非同期実行時 |
| BR-123-3 | エラー変換共用 | getaddrinfo()と同じエラー変換関数を使用 | 常時 |
| BR-123-4 | バッファ内蔵 | host/serviceはリクエスト構造体内のバッファに格納される | 常時 |

### 計算ロジック

salenの計算:
```
AF_INET  → salen = sizeof(struct sockaddr_in)
AF_INET6 → salen = sizeof(struct sockaddr_in6)
```

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

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EINVAL | パラメータエラー | req==NULL、addr==NULL、不正なアドレスファミリ | パラメータを修正 |
| UV_EAI_AGAIN | 一時的失敗 | DNS逆引き一時エラー | リトライ |
| UV_EAI_FAIL | 永続的失敗 | DNS逆引き永続エラー | DNS設定を確認 |
| UV_EAI_NONAME | 名前不明 | 逆引きできない | アドレスを確認 |
| UV_EAI_CANCELED | キャンセル | uv_cancel()によりキャンセル | 必要に応じて再実行 |

### リトライ仕様

ユーザー側でリトライを実装する必要がある。

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

該当なし。

## パフォーマンス要件

DNS逆引きはSLOW_IOとしてスレッドプールで実行される。ネットワーク応答時間に依存するため、数十ミリ秒から数秒程度かかる可能性がある。

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

- DNS逆引き結果は偽装可能であるため、セキュリティ判断の唯一の根拠として使用すべきではない
- host/serviceバッファはリクエスト構造体内の固定サイズバッファであり、バッファオーバーフローの心配はない

## 備考

- `uv__getaddrinfo_translate_error()` をアドレス解決機能と共用しており、コードの重複を避けている

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | **1016-1022行目**: `uv_getnameinfo_s`構造体。UV_REQ_FIELDS、loopポインタ、プラットフォーム固有のプライベートフィールド（storage, flags, host, service, retcode, work_req等）を持つ |
| 1-2 | uv.h | `include/uv.h` | **1024-1028行目**: `uv_getnameinfo()`の関数シグネチャ |

**読解のコツ**: `UV_GETNAMEINFO_PRIVATE_FIELDS`にはsockaddr_storage型のstorageフィールドが含まれ、入力アドレスのコピーを保持する。host/serviceは固定サイズのcharバッファである。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | getnameinfo.c | `src/unix/getnameinfo.c` | **81-121行目**: `uv_getnameinfo()`関数本体。バリデーション、アドレスコピー、リクエスト初期化、非同期/同期分岐 |

**主要処理フロー**:
1. **86-87行目**: パラメータバリデーション
2. **89-99行目**: アドレスファミリ判定とstorageへのコピー
3. **101-107行目**: リクエスト初期化
4. **109-121行目**: 非同期/同期の分岐

#### Step 3: ワーカー処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | getnameinfo.c | `src/unix/getnameinfo.c` | **31-53行目**: `uv__getnameinfo_work()`。salenの計算とgetnameinfo()呼び出し |
| 3-2 | getnameinfo.c | `src/unix/getnameinfo.c` | **55-74行目**: `uv__getnameinfo_done()`。リクエスト登録解除とコールバック呼び出し |

**主要処理フロー**:
- **38-43行目**: アドレスファミリに応じたsalen計算
- **45-51行目**: getnameinfo()システムコール呼び出し
- **52行目**: エラーコード変換（uv__getaddrinfo_translate_error共用）
- **64-66行目**: キャンセル時のretcode設定
- **72-73行目**: コールバック呼び出し

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

```
uv_getnameinfo() [src/unix/getnameinfo.c:81]
    │
    +-- uv__req_init() [src/uv-common.h]
    │       └── リクエスト初期化
    │
    +-- uv__work_submit() [src/threadpool.c:276]  ※非同期時
    │       └── post(&w->wq, UV__WORK_SLOW_IO)
    │
    +-- uv__getnameinfo_work() [src/unix/getnameinfo.c:31]
    │       +-- getnameinfo() [libc]
    │       └── uv__getaddrinfo_translate_error() [src/unix/getaddrinfo.c:39]
    │
    └── uv__getnameinfo_done() [src/unix/getnameinfo.c:55]
            +-- uv__req_unregister()
            └── req->getnameinfo_cb() コールバック呼び出し
```

### データフロー図

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

struct sockaddr* addr ──▶ uv_getnameinfo()
int flags ─────────────┘       │
                          [storageにコピー]
                               │
                          [スレッドプール]
                               │
                          getnameinfo()
                               │
                          [コールバック] ──▶ host (char*)
                                           service (char*)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | API定義（uv_getnameinfo_t構造体、関数宣言） |
| getnameinfo.c | `src/unix/getnameinfo.c` | ソース | Unix系プラットフォームの実装 |
| getnameinfo.c | `src/win/getnameinfo.c` | ソース | Windowsプラットフォームの実装 |
| getaddrinfo.c | `src/unix/getaddrinfo.c` | ソース | エラーコード変換関数の定義元 |
| threadpool.c | `src/threadpool.c` | ソース | スレッドプール連携 |
