# 機能設計書 19-バッファサイズ制御

## 概要

`uv_send_buffer_size()`/`uv_recv_buffer_size()`により送受信バッファサイズを取得・設定する機能の設計書である。

### 本機能の処理概要

**業務上の目的・背景**：ネットワーク通信においてソケットの送受信バッファサイズはパフォーマンスに大きく影響する。高スループットが必要な場合はバッファサイズを拡大し、メモリ制約がある場合は縮小する必要がある。本機能はTCP、UDP、パイプハンドルに対するOS側のソケットバッファサイズの取得・設定手段を提供する。

**機能の利用シーン**：大量データ転送時のバッファ最適化、メモリ使用量の制御、ネットワークパフォーマンスチューニング等に使用される。`*value == 0`の場合はバッファサイズを取得（GET）し、`*value != 0`の場合はバッファサイズを設定（SET）する。

**主要な処理内容**：
1. ハンドル型がTCP、UDP、パイプのいずれかであることを確認する
2. ハンドルからファイルディスクリプタを取得する
3. `*value == 0`の場合：`getsockopt(SO_RCVBUF/SO_SNDBUF)`でバッファサイズを取得
4. `*value != 0`の場合：`setsockopt(SO_RCVBUF/SO_SNDBUF)`でバッファサイズを設定

**関連システム・外部連携**：OS側のソケットオプション（`getsockopt`/`setsockopt`）を使用する。

**権限による制御**：バッファサイズの上限はOSのカーネルパラメータ（Linux: `/proc/sys/net/core/rmem_max`等）に制約される場合がある。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 7 | ハンドル基底 | 主機能 | uv_send_buffer_size()/uv_recv_buffer_size()による送受信バッファ制御のAPI定義 |

## 機能種別

データ取得・設定（ソケットオプション制御）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| handle | uv_handle_t* | Yes | 対象のハンドル（TCP/UDP/パイプ） | NULLの場合UV_EINVAL |
| value | int* | Yes | 取得時は0を設定して渡す。設定時は希望値を設定して渡す | NULLの場合UV_EINVAL |

### 入力データソース

呼び出し元から渡されるハンドル構造体ポインタとバッファサイズ値へのポインタ。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | int | 成功時0、エラー時は負のエラーコード |
| *value | int | 取得時：現在のバッファサイズ（バイト）。設定時は変更なし |

### 出力先

戻り値として呼び出し元へ返却。取得時は`*value`にバッファサイズが書き込まれる。

## 処理フロー

### 処理シーケンス

```
1. uv_send_buffer_size() / uv_recv_buffer_size()が呼び出される
2. uv__socket_sockopt()に委譲（SO_SNDBUF / SO_RCVBUF）
   2a. handleまたはvalueがNULLならUV_EINVALを返す
   2b. ハンドル型チェック（TCP/UDP/パイプのみ対応）
   2c. ハンドルからFDを取得
   2d. *value == 0: getsockopt()でバッファサイズを取得
   2e. *value != 0: setsockopt()でバッファサイズを設定
3. エラーの場合はUV__ERR(errno)を返す
```

### フローチャート

```mermaid
flowchart TD
    A[呼び出し] --> B{handle/value NULL?}
    B -->|Yes| C[UV_EINVAL]
    B -->|No| D{ハンドル型?}
    D -->|TCP/PIPE| E[uv__stream_fdでFD取得]
    D -->|UDP| F[io_watcher.fdでFD取得]
    D -->|その他| G[UV_ENOTSUP]
    E --> H{*value == 0?}
    F --> H
    H -->|Yes| I[getsockopt]
    H -->|No| J[setsockopt]
    I --> K{成功?}
    J --> K
    K -->|Yes| L[return 0]
    K -->|No| M[return UV__ERR]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-19-01 | GET/SET判定 | *value == 0ならGET、*value != 0ならSET | 常時 |
| BR-19-02 | 対応ハンドル型 | TCP、UDP、パイプのみ対応。他のハンドル型はUV_ENOTSUPを返す | 常時 |
| BR-19-03 | OS制約 | 設定値がOSの上限を超える場合、OSが自動的に上限値に調整する | 設定時 |

### 計算ロジック

特になし。OSのgetsockopt/setsockoptへの委譲。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EINVAL | パラメータエラー | handleまたはvalueがNULL | 引数を確認する |
| UV_ENOTSUP | 非対応 | TCP/UDP/パイプ以外のハンドル型 | 対応するハンドル型を使用する |
| UV__ERR(errno) | システムエラー | getsockopt/setsockoptが失敗 | エラー内容に応じて対処 |

### リトライ仕様

リトライ不要。

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

該当なし。

## パフォーマンス要件

O(1)の定数時間。システムコール1回の呼び出し。

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

バッファサイズの過大な設定はメモリ枯渇につながる可能性がある。アプリケーション側で適切な上限値を設けるべきである。

## 備考

- Linuxではsetsockoptで設定した値の実際の効果はカーネルバージョンに依存する場合がある
- 参照: include/uv.h L506-507

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | **L506-507**: uv_send_buffer_size()/uv_recv_buffer_size()のAPI宣言 |

**読解のコツ**: 両関数とも同じシグネチャ`(uv_handle_t*, int*)`を持ち、内部で同じ`uv__socket_sockopt()`に委譲する。違いはソケットオプション名（SO_SNDBUF/SO_RCVBUF）のみ。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | uv-common.c | `src/uv-common.c` | **L660-666**: uv_recv_buffer_size()とuv_send_buffer_size()の実装。uv__socket_sockopt()に委譲 |

**主要処理フロー**:
1. **660行目**: `uv_recv_buffer_size()` → `uv__socket_sockopt(handle, SO_RCVBUF, value)`
2. **664行目**: `uv_send_buffer_size()` → `uv__socket_sockopt(handle, SO_SNDBUF, value)`

#### Step 3: 内部関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | core.c (unix) | `src/unix/core.c` | **L240-266**: `uv__socket_sockopt()`の実装。FD取得、getsockopt/setsockopt呼び出し |

**主要処理フロー**:
- **245-246行目**: handleまたはvalueのNULLチェック → UV_EINVAL
- **248-253行目**: ハンドル型によるFD取得（TCP/PIPE: uv__stream_fd、UDP: io_watcher.fd、その他: UV_ENOTSUP）
- **257-258行目**: `*value == 0`ならgetsockopt
- **259-260行目**: `*value != 0`ならsetsockopt

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

```
uv_send_buffer_size(handle, value)    [src/uv-common.c:664]
uv_recv_buffer_size(handle, value)    [src/uv-common.c:660]
    │
    └─ uv__socket_sockopt(handle, optname, value)  [src/unix/core.c:240]
           │
           ├─ NULL チェック
           ├─ ハンドル型判定 → FD取得
           │   ├─ TCP/PIPE → uv__stream_fd()
           │   ├─ UDP → io_watcher.fd
           │   └─ その他 → UV_ENOTSUP
           │
           └─ getsockopt() / setsockopt()   [システムコール]
```

### データフロー図

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

uv_handle_t* handle ───────> FD取得 ─────────────────────>
int* value ────────────────> getsockopt/setsockopt ────────> *value(GET時)
                                                             return 0 or error
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | 公開API宣言（L506-507） |
| uv-common.c | `src/uv-common.c` | ソース | 公開API実装（L660-666） |
| core.c (unix) | `src/unix/core.c` | ソース | uv__socket_sockopt()実装（L240-266） |
| handle.c (win) | `src/win/handle.c` | ソース | Windows実装 |
