# 機能設計書 6-net

## 概要

本ドキュメントは、Node.jsのnetモジュール（TCP/IPソケット通信機能）の機能設計を記載する。netモジュールは、TCP/IPベースのネットワーク通信およびIPC（プロセス間通信）用のUnixドメインソケット/Windowsパイプを提供するコアモジュールである。

### 本機能の処理概要

netモジュールは、非同期I/Oに基づくTCPサーバー・クライアント機能を提供する。ストリームベースのDuplexインターフェースを実装し、双方向のデータ通信を実現する。

**業務上の目的・背景**：TCP/IPはインターネット通信の基盤プロトコルであり、HTTPやHTTPS、データベース接続など多くの上位プロトコルがTCP上に構築されている。netモジュールはこれらの基盤となる低レベルのソケット通信機能を提供し、カスタムプロトコルの実装や高度なネットワークアプリケーションの構築を可能にする。

**機能の利用シーン**：
- カスタムTCPサーバー/クライアントの構築
- プロセス間通信（IPCソケット）
- 低レベルネットワークプログラミング
- リバースプロキシ、ロードバランサーの実装
- HTTPモジュールの基盤

**主要な処理内容**：
1. TCPサーバーの作成と接続受付（Server, createServer）
2. TCPクライアント接続（Socket, connect, createConnection）
3. データの送受信（Duplexストリーム）
4. IPアドレスのバリデーション（isIP, isIPv4, isIPv6）
5. Keep-Alive設定
6. 接続タイムアウト管理
7. クラスターモードでの負荷分散

**関連システム・外部連携**：
- tcp_wrapバインディング（C++レイヤー）
- pipe_wrapバインディング（IPC）
- streamモジュール（Duplexストリーム）
- dnsモジュール（名前解決）

**権限による制御**：1024未満のポート番号（特権ポート）はroot/管理者権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 直接関連する画面なし |

## 機能種別

ネットワーク通信 / ストリーム処理 / サーバー構築

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| port | number | No | 接続/待受ポート番号 | validatePort |
| host | string | No | 接続先ホスト名/IPアドレス | validateString |
| path | string | No | Unixソケット/Windowsパイプパス | validateString |
| options | object | No | 接続/サーバーオプション | validateObject |
| allowHalfOpen | boolean | No | 片方向接続の許可 | - |
| pauseOnConnect | boolean | No | 接続時に一時停止 | - |
| noDelay | boolean | No | Nagleアルゴリズム無効化 | - |
| keepAlive | boolean | No | Keep-Alive有効化 | - |
| keepAliveInitialDelay | number | No | Keep-Alive初期遅延（ms） | validateNumber |
| backlog | number | No | 接続キューサイズ | - |
| signal | AbortSignal | No | 中断シグナル | validateAbortSignal |

### 入力データソース

- アプリケーションコード：接続パラメータ、サーバー設定
- ネットワーク：クライアントからの接続要求、データ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| server | Server | TCPサーバーインスタンス |
| socket | Socket | ソケットインスタンス |
| address | object | アドレス情報（port, address, family） |
| bytesRead | number | 読み取りバイト数 |
| bytesWritten | number | 書き込みバイト数 |

### 出力先

- サーバー：接続クライアントへのデータ送信
- クライアント：接続先サーバーへのデータ送信
- イベント：'connection', 'data', 'end', 'close', 'error'等

## 処理フロー

### 処理シーケンス（サーバー）

```
1. createServer()でServerインスタンス生成
   └─ EventEmitter継承、オプション設定
2. server.listen()でポートバインド
   └─ createServerHandle()でTCPハンドル作成
   └─ setupListenHandle()で待受開始
3. 接続受付
   └─ onconnection()コールバック
   └─ Socketインスタンス生成
4. 'connection'イベント発火
5. データ送受信
   └─ Duplexストリームとして処理
6. 切断処理
   └─ server.close()で新規接続拒否
```

### 処理シーケンス（クライアント）

```
1. connect()/createConnection()でSocket生成
   └─ normalizeArgs()でオプション正規化
2. lookupAndConnect()でDNS解決
   └─ autoSelectFamily対応
3. internalConnect()でTCP接続
   └─ TCPConnectWrap/PipeConnectWrap使用
4. afterConnect()で接続完了
   └─ 'connect'イベント発火
5. データ送受信
   └─ _read()/_write()でストリーム処理
6. 切断
   └─ socket.end()/destroy()
```

### フローチャート

```mermaid
flowchart TD
    A[createServer] --> B[Server生成]
    B --> C[listen]
    C --> D[createServerHandle]
    D --> E[TCP/Pipeハンドル]
    E --> F[setupListenHandle]
    F --> G[backlog設定]
    G --> H{接続あり?}
    H -->|Yes| I[onconnection]
    I --> J[Socket生成]
    J --> K[connectionイベント]
    K --> L[データ送受信]
    L --> H
    H -->|close| M[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | デフォルトバックログ | 511（カーネルで512に切り上げ） | listen時 |
| BR-002 | IPv6優先 | デフォルトでIPv6にバインド試行 | address未指定時 |
| BR-003 | autoSelectFamily | IPv4/IPv6を交互に試行 | デフォルト有効 |
| BR-004 | 最小タイムアウト | autoSelectFamilyAttemptTimeout最小値10ms | タイムアウト設定時 |
| BR-005 | allowHalfOpenデフォルト | false（片方向接続不可） | デフォルト |
| BR-006 | BlockList | IPアドレスのブロックリスト | 接続/受付時 |

### 計算ロジック

- backlog: カーネルが roundup_pow_of_two(backlogsize + 1) で計算
- keepAliveInitialDelay: ミリ秒を秒に変換 (~~(ms / 1000))

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

本モジュールはデータベースを直接操作しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ERR_INVALID_ADDRESS_FAMILY | バリデーション | 無効なアドレスファミリー | IPv4/IPv6を指定 |
| ERR_INVALID_IP_ADDRESS | バリデーション | 無効なIPアドレス | IPアドレス形式確認 |
| ERR_IP_BLOCKED | セキュリティ | BlockListでブロック | ブロックリスト確認 |
| ERR_SERVER_ALREADY_LISTEN | 状態エラー | サーバー既にlisten中 | 新規サーバー作成 |
| ERR_SERVER_NOT_RUNNING | 状態エラー | サーバー未起動 | listen()を先に呼出 |
| ERR_SOCKET_CLOSED | 状態エラー | ソケット閉鎖済み | 新規ソケット作成 |
| ERR_SOCKET_CLOSED_BEFORE_CONNECTION | 接続エラー | 接続前にクローズ | 接続完了を待つ |
| ERR_SOCKET_CONNECTION_TIMEOUT | タイムアウト | 接続タイムアウト | タイムアウト値調整 |
| EADDRINUSE | システム | ポート使用中 | 別ポート使用 |

### リトライ仕様

アプリケーション層でのリトライ実装が必要。autoSelectFamilyで複数アドレス試行をサポート。

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

TCPはストリームベースのステートフルプロトコル。ソケット状態はconnecting, open, readOnly, writeOnly, closedで管理。

## パフォーマンス要件

- setNoDelay()でNagleアルゴリズム無効化による低レイテンシ
- setKeepAlive()で接続維持
- reusePortオプションで複数プロセスでのポート共有
- 非同期I/Oによる高スループット

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

- BlockListによるIPアドレスフィルタリング
- maxConnectionsによる接続数制限
- AbortSignalによる処理中断
- 特権ポート（1024未満）へのバインドは権限が必要

## 備考

- SocketはDuplexストリームを継承
- ServerはEventEmitterを継承
- tcp_wrap, pipe_wrapのC++バインディングを使用
- diagnostics_channelでnet.client.socket, net.server.socketチャネルを提供

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | net.js | `lib/net.js` | Socket, Serverクラスの継承関係 |

**読解のコツ**: SocketはDuplexストリームを継承（516-517行目）、ServerはEventEmitterを継承（1823-1824行目）。kHandle, kBufferなどのSymbolが内部状態管理の鍵。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | net.js | `lib/net.js` | 公開API定義（2477-2501行目） |

**主要処理フロー**:
1. **218-220行目**: createServer()関数
2. **235-246行目**: connect()関数
3. **362-515行目**: Socket関数（コンストラクタ）
4. **1763-1824行目**: Server関数（コンストラクタ）

#### Step 3: ソケット接続処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | net.js | `lib/net.js` | 接続処理の実装 |

**主要処理フロー**:
- **1222-1288行目**: Socket.prototype.connect() - 接続開始
- **1310-1440行目**: lookupAndConnect() - DNS解決と接続
- **1046-1115行目**: internalConnect() - 実際の接続処理
- **1590-1650行目**: afterConnect() - 接続完了コールバック
- **1118-1220行目**: internalConnectMultiple() - autoSelectFamily対応

#### Step 4: サーバー処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | net.js | `lib/net.js` | サーバー処理の実装 |

**主要処理フロー**:
- **2038-2160行目**: Server.prototype.listen() - 待受開始
- **1830-1886行目**: createServerHandle() - ハンドル生成
- **1888-1971行目**: setupListenHandle() - 待受設定
- **2235-2308行目**: onconnection() - 接続受付

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

```
net.createServer(options, connectionListener)
    │
    └─ new Server(options, connectionListener)
           │
           ├─ EventEmitter.call(this)
           │
           └─ オプション設定（allowHalfOpen, pauseOnConnect等）

server.listen(port, host, backlog, cb)
    │
    └─ normalizeArgs()
           │
           ├─ lookupAndListen() [host指定時]
           │      └─ dns.lookup()
           │             └─ listenInCluster()
           │
           └─ listenInCluster()
                  │
                  ├─ cluster.isPrimary → _listen2()
                  │
                  └─ cluster.isWorker → cluster._getServer()
                         └─ listenOnPrimaryHandle()

_listen2() [setupListenHandle]
    │
    ├─ createServerHandle(address, port, ...)
    │      │
    │      ├─ new TCP(TCPConstants.SERVER) [TCP]
    │      │
    │      └─ new Pipe(PipeConstants.SERVER) [IPC]
    │
    ├─ this._handle.listen(backlog)
    │
    └─ emit('listening')

net.connect(options)
    │
    └─ new Socket(options)
           │
           └─ socket.connect(options)
                  │
                  ├─ pipe → internalConnect(path)
                  │
                  └─ TCP → lookupAndConnect()
                         │
                         ├─ dns.lookup()
                         │
                         ├─ autoSelectFamily → lookupAndConnectMultiple()
                         │      └─ internalConnectMultiple()
                         │
                         └─ internalConnect()
                                │
                                ├─ new TCPConnectWrap()
                                │
                                ├─ this._handle.connect()
                                │
                                └─ afterConnect()
                                       └─ emit('connect')
```

### データフロー図

```
[サーバー側]

createServer ───▶ Server ───▶ listen ───▶ createServerHandle
                                              │
                                         TCP/Pipeハンドル
                                              │
                                         listen(backlog)
                                              │
                                         onconnection ◀─── クライアント接続
                                              │
                                         new Socket
                                              │
                                         'connection'イベント

[クライアント側]

connect ───▶ Socket ───▶ lookupAndConnect
                              │
                         dns.lookup
                              │
                         internalConnect
                              │
                         TCPConnectWrap
                              │
                         _handle.connect()
                              │
                         afterConnect
                              │
                         'connect'イベント

[データ送受信]

socket.write(data)          socket.on('data')
       │                           │
   _write()                    _read()
       │                           │
   writeGeneric()           tryReadStart()
       │                           │
   _handle.write()          _handle.readStart()
       │                           │
       ▼                           ▼
    TCP送信                     TCP受信
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| net.js | `lib/net.js` | ソース | 公開API定義（メイン） |
| internal/net.js | `lib/internal/net.js` | ソース | 内部ユーティリティ（isIP等） |
| stream.js | `lib/stream.js` | ソース | Duplexストリーム基底 |
| events.js | `lib/events.js` | ソース | EventEmitter基底 |
| dns.js | `lib/dns.js` | ソース | DNS名前解決 |
| internal/blocklist.js | `lib/internal/blocklist.js` | ソース | BlockList実装 |
| internal/socketaddress.js | `lib/internal/socketaddress.js` | ソース | SocketAddress実装 |
