# 機能設計書 103-HeadlessVnc

## 概要

本ドキュメントは、Avalonia UIフレームワークにおけるHeadlessVNC機能の機能設計書である。VNCプロトコルを使用してヘッドレスAvaloniaアプリケーションをリモート表示する機能を提供する。

### 本機能の処理概要

HeadlessVncは、ヘッドレス環境で動作するAvaloniaアプリケーションの画面をVNC（Virtual Network Computing）プロトコルを通じてリモートクライアントに配信する機能を提供する。サーバー環境やDockerコンテナで実行されるアプリケーションを、リモートのVNCビューワーから操作可能にする。

**業務上の目的・背景**：サーバー環境でGUIアプリケーションを実行する場合、直接ディスプレイに接続できないことが多い。HeadlessVncは、VNCプロトコルを介してリモートからアプリケーションのGUIを確認・操作できるようにし、サーバーサイドでのGUIアプリケーション運用やデバッグを可能にする。組み込みシステムやキオスク端末のリモート管理にも活用できる。

**機能の利用シーン**：
- サーバー上で動作するAvaloniaアプリケーションのリモート表示
- DockerコンテナやKubernetesポッド内のGUIアプリケーション操作
- 組み込みLinux環境でのGUIアプリケーションリモートアクセス
- CI/CD環境でのビジュアルデバッグ
- ヘッドレスサーバーでのデスクトップアプリケーション運用

**主要な処理内容**：
1. VNCサーバーの起動とクライアント接続の待ち受け
2. Avaloniaフレームバッファ内容のVNCフレームバッファへの転送
3. VNCポインターイベントのAvalonia入力イベントへの変換
4. VNCキーイベントのAvalonia入力イベントへの変換
5. オプショナルなパスワード認証の提供
6. ウィンドウサイズの動的変更サポート

**関連システム・外部連携**：
- RemoteViewing.Vncライブラリ（VNCサーバー実装）
- Avalonia.Headlessプラットフォーム
- VNCビューワー（クライアント側）

**権限による制御**：VNCパスワード認証による接続制御が可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | VNCセッション | 主画面 | VNCクライアントに表示されるAvaloniaウィンドウ |

## 機能種別

リモート表示 / プロトコル変換 / イベント処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| host | string | No | バインドするIPアドレス | null/空の場合はLoopback |
| port | int | Yes | VNCサーバーポート番号 | 有効なポート番号 |
| password | string | No | 接続認証パスワード | null/空の場合は認証なし |
| args | string[] | Yes | アプリケーション起動引数 | - |
| shutdownMode | ShutdownMode | No | シャットダウンモード | デフォルトOnLastWindowClose |

### 入力データソース

- VNCクライアントからの接続要求
- VNCクライアントからのポインター/キーボードイベント

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| VncFramebuffer | VncFramebuffer | VNCクライアントに送信されるフレームバッファ |
| ExtendedDesktopSizeStatus | ExtendedDesktopSizeStatus | リサイズ結果ステータス |

### 出力先

- VNCクライアント（ネットワーク経由）

## 処理フロー

### 処理シーケンス

```
1. StartWithHeadlessVncPlatform呼び出し
   └─ TCPリスナーの起動
2. UseHeadlessでプラットフォーム初期化
   └─ UseHeadlessDrawing=falseで実描画を有効化
   └─ FrameBufferFormat=Bgra8888を指定
3. VNCクライアント接続待ち
   └─ AcceptTcpClientAsync
4. VNCセッション作成
   └─ 認証方式の設定（None/Password）
   └─ HeadlessVncFramebufferSourceの設定
5. セッション開始
   └─ イベントハンドラー登録（PointerChanged, KeyChanged）
6. フレーム配信ループ
   └─ Capture()でフレームバッファ取得
   └─ VNCクライアントへ送信
```

### フローチャート

```mermaid
flowchart TD
    A[StartWithHeadlessVncPlatform] --> B[TCPリスナー起動]
    B --> C[UseHeadless設定]
    C --> D[アプリケーション起動]
    D --> E{クライアント接続待ち}
    E --> F[VncServerSession作成]
    F --> G{パスワード設定?}
    G -->|Yes| H[Password認証設定]
    G -->|No| I[None認証設定]
    H --> J[HeadlessVncFramebufferSource設定]
    I --> J
    J --> K[Session.Connect]
    K --> L{イベント受信}
    L -->|PointerChanged| M[マウスイベント変換]
    L -->|KeyChanged| N[キーイベント変換]
    M --> O[Dispatcher.UIThread.Post]
    N --> O
    O --> L
    L -->|Capture要求| P[フレームバッファキャプチャ]
    P --> Q[VNCクライアントへ送信]
    Q --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-103-1 | フレームバッファ形式 | Bgra8888形式でフレームバッファを作成 | 常時 |
| BR-103-2 | VNCピクセル形式 | RGB32形式でVNCフレームバッファを作成 | 常時 |
| BR-103-3 | 認証方式 | パスワード指定時はPassword認証、未指定時はNone認証 | 接続時 |
| BR-103-4 | リサイズサポート | SupportsResizing=trueで動的リサイズ可能 | クライアント要求時 |

### 計算ロジック

VNCボタン状態からRawInputModifiersへの変換:
```
modifiers = (RawInputModifiers)(((int)buttons & 7) << 4)
```

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

データベース操作なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| MAIN_WINDOW_NULL | InvalidOperationException | MainWindowが初期化されていない | アプリケーション起動順序を確認 |
| CONNECTION_ERROR | Exception | クライアント接続エラー | ログ出力後、次の接続を待機 |

### リトライ仕様

- 接続エラー時は100ms待機後、次のクライアント接続を受け付け

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

トランザクションなし。

## パフォーマンス要件

- フレームバッファの差分転送でネットワーク帯域を最適化（VNCプロトコル機能）
- フレームバッファのコピーは必要時のみ実行

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

- パスワード認証でアクセス制御可能
- デフォルトはLoopbackアドレスのみ（外部からの直接接続を防止）
- VNC通信自体は暗号化されないため、必要に応じてSSHトンネル等を使用

## 備考

- RemoteViewing.Vncライブラリに依存
- VNC拡張仕様（Extended Desktop Size）をサポート

---

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

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

### 推奨読解順序

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

VNCフレームバッファソースの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | HeadlessVncFramebufferSource.cs | `src/Headless/Avalonia.Headless.Vnc/HeadlessVncFramebufferSource.cs` | IVncFramebufferSource実装、VncFramebufferの管理 |

**読解のコツ**: VncButton列挙型（303-311行目）でLeft/Middle/Right/ScrollUp/ScrollDownを定義。CheckedButtons配列で状態チェック対象を限定。

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

処理の起点となるAppBuilder拡張メソッドを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | HeadlessVncPlatformExtensions.cs | `src/Headless/Avalonia.Headless.Vnc/HeadlessVncPlatformExtensions.cs` | StartWithHeadlessVncPlatform（27-106行目）がエントリーポイント |

**主要処理フロー**:
1. **55-56行目**: TCPリスナーの作成と起動
2. **57-62行目**: UseHeadlessでプラットフォーム初期化
3. **63-105行目**: AfterApplicationSetupでVNCサーバー設定
4. **72-78行目**: VncServerSessionの作成と認証設定

#### Step 3: フレームバッファ処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | HeadlessVncFramebufferSource.cs | `src/Headless/Avalonia.Headless.Vnc/HeadlessVncFramebufferSource.cs` | Capture()（316-340行目）でフレームバッファをVNC形式に変換 |

**主要処理フロー**:
- **316-340行目**: Capture()でGetLastRenderedFrame()を呼び出し、VncFramebufferにコピー
- **342-350行目**: SetDesktopSize()でウィンドウサイズ変更

#### Step 4: 入力イベント変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | HeadlessVncFramebufferSource.cs | `src/Headless/Avalonia.Headless.Vnc/HeadlessVncFramebufferSource.cs` | コンストラクタ（20-88行目）でPointerChanged/KeyChangedイベントハンドラーを登録 |

**主要処理フロー**:
- **23-59行目**: PointerChangedイベントでマウス操作をAvalonia入力に変換
- **62-87行目**: KeyChangedイベントでキーボード入力を変換
- **111-300行目**: TranslateKey()でVNCキーシンボルをAvaloniaキーに変換

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

```
StartWithHeadlessVncPlatform (HeadlessVncPlatformExtensions.cs)
    │
    ├─ TcpListener.Start()
    │
    ├─ UseHeadless()
    │      └─ AvaloniaHeadlessPlatform.Initialize()
    │
    └─ AfterApplicationSetup (ラムダ)
           │
           └─ Startup イベントハンドラー
                  │
                  ├─ AcceptTcpClientAsync() [ループ]
                  │
                  ├─ VncServerSession作成
                  │      └─ PasswordProvided イベント設定
                  │
                  └─ SetFramebufferSource
                         └─ HeadlessVncFramebufferSource (constructor)
                                │
                                ├─ PointerChanged += ハンドラー
                                │      └─ Window.MouseMove/Down/Up/Wheel
                                │
                                └─ KeyChanged += ハンドラー
                                       └─ Window.KeyPress/Release/TextInput
```

### データフロー図

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

VNCクライアント ─────────▶ TcpListener ─────────────▶ VncServerSession
(接続要求)                                                    │
                                                              ▼
VNCポインター ─────────▶ PointerChangedイベント ─────▶ Window.MouseXxx()
イベント                    │
                           └─▶ RawInputModifiers計算

VNCキーイベント ────────▶ KeyChangedイベント ────────▶ Window.KeyXxx()
                           │
                           └─▶ TranslateKey()

Avalonia ─────────────▶ GetLastRenderedFrame() ──────▶ VncFramebuffer
レンダリング                   │                          │
                              └─▶ Capture()              │
                                                         ▼
                                              VNCクライアント（画面表示）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| HeadlessVncPlatformExtensions.cs | `src/Headless/Avalonia.Headless.Vnc/HeadlessVncPlatformExtensions.cs` | ソース | AppBuilder拡張メソッド、VNCサーバー起動 |
| HeadlessVncFramebufferSource.cs | `src/Headless/Avalonia.Headless.Vnc/HeadlessVncFramebufferSource.cs` | ソース | VNCフレームバッファソース実装 |
| AvaloniaVncLogger.cs | `src/Headless/Avalonia.Headless.Vnc/AvaloniaVncLogger.cs` | ソース | VNCライブラリ用ロガー |
