# P2Pファイル転送

## 概要

HyperDrive の「合言葉共有」機能が WebRTC DataChannel を使って
ブラウザ間で直接ファイルを転送する仕組みを説明する。

**「サーバーを介さない」の正確な意味**

| 経由するもの | 経由しないもの |
|---|---|
| 接続ネゴシエーション（SDP・ICE） | ファイルのバイナリ実体 |
| ファイルメタデータ（名前・サイズ等）の REST 登録 | — |
| 合言葉（ルームID）の Valkey 一時保存 | — |

ファイルの**実体（バイナリデータ）**は HyperDrive サーバーを通過しない。
一方、**誰が誰に何を送ろうとしているか**を示すメタデータや接続確立のための
シグナリング情報はサーバー経由となる。後述の表を参照。

## 通信フロー全体図

```
[送信者ブラウザ]  ←(1)WS→  [HyperDrive サーバー]  ←(1)WS→  [受信者ブラウザ]
       ↕                          ↕
    (2)STUN                    (Valkey)
       ↕
[送信者ブラウザ] ←────────(3) WebRTC DataChannel ────────→ [受信者ブラウザ]
                         （ファイルデータはここを通る）
```

各番号について:

1. WebSocket シグナリング（SDP offer/answer・ICE candidates）— **サーバー経由**
2. STUN による外部IP確認（異なるネットワーク間でのP2P確立に必要）
3. WebRTC DataChannel によるファイル直接転送 — **サーバー不経由**

## サーバーを経由するものとしないもの

| データ種別 | 経路 | 備考 |
|---|---|---|
| SDPオファー/アンサー | HyperDriveサーバー経由（WebSocket） | 接続ネゴシエーション情報 |
| ICE候補（IPアドレス・ポート情報） | HyperDriveサーバー経由（WebSocket） | NATトラバーサル用 |
| ファイルメタデータ（名前・サイズ・ハッシュ） | HyperDriveサーバー経由（REST POST /v1/files/watchword） | 合言葉生成のリクエスト時 |
| **ファイル実体（バイナリデータ）** | **サーバー不経由（WebRTC DataChannel）** | **P2P直接転送** |
| 合言葉（ルームID） | Valkey（一時保存、TTL10分） | ファイル実体は含まない |

### NATトラバーサルとTURNリレー

HyperDrive は同一LAN内だけでなく、インターネット越しの異なるネットワーク間での
使用も想定している。この場合、NATトラバーサルが必要になる。

**NATトラバーサルの流れ:**
1. 双方が STUN サーバーに問い合わせ、自分の外部IPアドレスとポートを取得
2. ICE候補としてシグナリングサーバー経由で相手に通知
3. 直接P2P接続を試みる（多くのNAT環境では成功）

**TURN リレーが必要になるケース:**
- 送受信者の一方または双方が Symmetric NAT 配下にある場合
- 直接P2P が確立できない場合、TURN サーバーがファイルデータをリレーする
- TURNを経由してもDTLS暗号化は維持されるが、TURNサーバー管理者は
  暗号化されたパケットを通過させる（内容は読めない）

**自己ホスト構成での注意:**
- TURN サーバーも自己管理になるため、第三者サービスへのデータ通過は発生しない
- 同一LAN内での使用であれば STUN/TURN ともに不要

## セキュアなファイル共有と言えるか

「セキュアか」の問いに対して、以下の軸で正直に評価する。

### ✅ セキュアと言える点

**ファイル実体の非通過性**

- ファイルのバイナリデータはHyperDriveサーバーに送信・保存されない
- サーバーにファイル内容のログが残らない
- 機密文書の転送時にサーバー管理者がアクセスできない

**DTLS暗号化（WebRTC DataChannel）**

- WebRTC DataChannel は DTLS（Datagram Transport Layer Security）で必ず暗号化される
- DTLS は TLS と同等の暗号強度（TLS 1.2/1.3 相当）
- 通信経路での盗聴が困難

**ファイル整合性検証**

- 送受信前後でファイルハッシュ（filehash）を比較し、改ざん・破損を検出できる

### ⚠️ 留意すべき点

**シグナリング時のメタデータ露出**

- ファイル名・サイズ・MIMEタイプ・送受信者IDはサーバーに送信される
- ファイル実体ではないが「誰が誰に何という名前のファイルを送ったか」はサーバーが把握可能

**接続相手の確認手段がない（既知の問題）**

- 合言葉を知っていれば誰でも受信者になれる
- 合言葉の安全な受け渡し（口頭・別チャネル経由）は利用者の責任
- 合言葉の推測攻撃のリスクあり（TTL10分で緩和されるが完全ではない）

**TURN経由時のプライバシー**

- インターネット越しに使用する場合、NATトラバーサルが必要になりTURNリレーが
  発生する可能性がある
- TURN経由時はファイルデータがTURNサーバーを通過するが、DTLS暗号化は維持される
  （TURNサーバーは暗号化パケットを転送するだけで内容は読めない）
- 自己ホスト構成でTURNサーバーも自己管理する場合、第三者へのデータ通過は発生しない
- 第三者TURNサービス（coturn等をクラウドで動かす場合）を使用する際は
  そのサーバー管理者が暗号化データを通過させることを認識すること

### 結論

「**ファイル実体がHyperDriveサーバーに保存されない**」という意味では
セキュアと言える。ただし「完全End-to-End暗号化でメタデータも保護される」
ではないため、「プライバシー重視のファイル直接転送機能」という表現が正確。

## チャンク分割転送

大容量ファイルを転送する際の仕組み:

- WebRTC DataChannel の MTU 制限（一般的に16KB〜64KB/チャンク）
- リクエストの `chunk_size` フィールドの役割
  - 合言葉共有 API（`POST /v1/files/watchword`）のリクエストで送信者が希望チャンクサイズを指定する
  - 送受信ブラウザはこの値を基準にファイルを分割し、DataChannel 上で順次送信する
- 受信側でチャンクを結合してファイルを再構成する流れ
  1. チャンク0〜N を順次受信（またはシーケンス番号で並べ替え）
  2. `ArrayBuffer` / `Blob` に結合
  3. 受信完了後、`filehash` とローカル計算ハッシュを照合
- 進捗表示のためのチャンク番号管理
  - 各チャンクに連番（0始まり）を付与し、UI は `受信済みチャンク数 / 総チャンク数` で進捗を表示する

## HyperDriveでの利用前提・制約

| 項目 | 内容 |
|---|---|
| 想定ネットワーク | 同一LAN内・インターネット越し（異なるネットワーク間）ともに対応 |
| TURN サーバー | LAN内なら不要 / LAN外（NAT越え）では直接P2P不可時に必要 |
| STUNサーバー | LAN内なら不要 / LAN外では外部IP取得のために必要 |
| ブラウザ要件 | WebRTC DataChannel 対応ブラウザ（Chrome/Firefox/Safari/Edge） |
| 最大ファイルサイズ | 未定義（メモリ制限に依存） |
| 同時接続 | 1対1（合言葉1つにつき1ペア） |
| セッション有効期限 | 10分（Valkey TTL） |

## 関連ドキュメント

- [合言葉共有 API仕様](../ファイル系/共有系/合言葉共有.md)
- [WebRTCシグナリング インフラ概要](WebRTCシグナリング.md)
- [WebSocketシグナリング エンドポイント](WebSocketシグナリングエンドポイント.md)
