# iKuai 4.0 扩展体系源码分析报告

> 产出时间：2026-08-28  
> 分析范围：AppMarket设备端(Shell+Lua)、PMD设备端(C daemon)、PMD服务端(ik_rc)、AppMarket服务端(docker-app)、OSPF固化方式、rc启动顺序  
> 目标：为统一扩展体系方案提供源码级分析依据  
> 图表格式：全部使用 mermaid（flowchart/graph/sequenceDiagram），不使用 ASCII art

---

## 目录

1. [架构总览](#1-架构总览)
2. [AppMarket设备端完整架构](#2-appmarket设备端完整架构)
3. [PMD设备端完整架构](#3-pmd设备端完整架构)
4. [PMD服务端(ik_rc)完整架构](#4-pmd服务端ik_rc完整架构)
5. [ipkg包格式+签名验证流程](#5-ipkg包格式签名验证流程)
6. [PMD包格式+AES加密流程](#6-pmd包格式aes加密流程)
7. [OSPF当前固化方式](#7-ospf当前固化方式)
8. [rc启动顺序](#8-rc启动顺序)
9. [设备启动数据流](#9-设备启动数据流)
10. [在线更新数据流](#10-在线更新数据流)
11. [离线安装数据流](#11-离线安装数据流)
12. [进程监控对比](#12-进程监控对比)
13. [两套体系对接点分析](#13-两套体系对接点分析)
14. [接口设计建议](#14-接口设计建议)

---

## 1. 架构总览

iKuai 4.0 有两套独立的扩展体系，各管各的，没有统一后端。

```mermaid
graph TB
    subgraph Device["iKuai 4.0 设备端"]
        subgraph AM["AppMarket 体系"]
            AM1["Shell function/appmarket 3166行"]
            AM2["Lua applist_control.lua 579行"]
            AM3["SQLite appmarket.db + apptmp.db"]
            AM4["type=0 原生应用 / type=1 Docker"]
            AM5["tar.gz ipkg 格式"]
            AM6["RSA-3072 SHA-256 签名"]
            AM7["有前端 Web UI"]
        end
        subgraph PMD["PMD 体系"]
            P1["C daemon ik_pmd 约7000行"]
            P2["自有协议 ikstd_prot + AES-256-CBC"]
            P3["JSON DB AES加密 .__DB"]
            P4["二进制包 .bin.pkg"]
            P5["AES-256-CBC + MD5 校验"]
            P6["无前端 4.0移除"]
        end
        RC["rc脚本启动顺序<br/>start_remote_services → ik_rc_client → pmd<br/>然后 boot_load_async appmarket.sh"]
    end
    subgraph Cloud["云端"]
        DA["docker-app<br/>签名工具 + 包仓库 + native-apps<br/>plugin.ikuai8.com API"]
        IKRC["ik_rc<br/>REST API + RPC + 设备管理 + AS注册<br/>pkgmanager.ikuai8.com:1863 / :15602"]
    end
    AM --> DA
    PMD --> IKRC
```

### 两套体系对比

| 维度 | AppMarket | PMD |
|------|-----------|-----|
| 语言 | Shell + Lua | C |
| 包格式 | tar.gz (ipkg) | .bin.pkg (AES加密shell脚本) |
| 签名 | RSA-3072 SHA-256 | 无签名，仅AES加密 |
| 数据库 | SQLite (appmarket.db) | JSON (AES加密 .__DB) |
| 云端协议 | HTTP REST (plugin.ikuai8.com) | 自有TCP协议 (ikstd_prot) |
| 进程监控 | Shell检查run.status文件 | C列表轮询ps/grep |
| 应用类型 | Docker容器 + 原生应用 | 纯二进制包 |
| 前端 | 有（Web UI通过SQLite） | 无 |
| 启动方式 | rc → appmarket.sh boot | rc → start_remote_services → pmd |
| 离线安装 | 支持（install_file上传） | 不支持（需服务端推送） |

---

## 2. AppMarket设备端完整架构

### 2.1 源码文件

| 文件 | 行数 | 功能 |
|------|------|------|
| `function/appmarket` | 3166 | 核心Shell函数库 |
| `script/appmarket.sh` | 与function/appmarket相同 | 入口脚本（include function/appmarket） |
| `script/sec/applist_control.lua` | 579 | 云端API通信（curl + SQLite缓存） |
| `etc/defaults/appmarket.conf` | 46 | SQLite表结构定义 |

### 2.2 SQLite表结构（appmarket.conf）

**applist表** — 已安装应用列表：

```
id, enabled, name, display_name, appid, timestamp, location, ico,
type(0=原生,1=docker), size, restart, current_version,
maintainer, maintainer_url, distributor, distributor_url,
origin(0=官方,3=离线上传), update_time, ignore_update,
install_path, category, sub_category, desc, desc_url, readme, changelog
```

**app_task_queue表** — 安装任务队列：

```
id, name, display_name, appid, path, status(0=未执行,1=安装中),
errexit, timestamp
```

### 2.3 核心函数清单

#### 初始化/启动

| 函数名 | 行号 | 功能 |
|--------|------|------|
| `boot()` | 45 | 创建目录、初始化临时DB、清理上传缓存、调用init |
| `init()` | 69 | 从SQLite读已安装列表，为每个应用执行`__exec_rule_init` |
| `__exec_rule_init()` | 93 | 创建/var/appmarket软链接、链接UI资源、按type调用native/container init |
| `clean_upload_cache()` | 56 | 清理离线上传的临时包目录 |
| `sync_apps()` | 1632 | 异步从云端拉取应用列表（`__apps_list_get`） |

#### 原生应用（type=0）管理

| 函数名 | 行号 | 功能 |
|--------|------|------|
| `__native_app_init()` | 335 | 先stop再start（如果enabled=yes） |
| `__native_app_start()` | 464 | 完整性验证 → 生成配置 → 执行start.sh |
| `__native_app_stop()` | 455 | 执行stop.sh |
| `__native_app_install()` | 484 | 完整性验证 → 生成配置 → PRE_INST.sh → start.sh → POST_INST.sh |
| `__native_app_uninstall()` | 510 | PRE_UNINST.sh → stop.sh → POST_UNINST.sh |
| `__native_app_verify_integrity()` | 344 | 核心安全函数：RSA签名验证 + SHA-256逐文件校验 |
| `__gen_native_config()` | 226 | 从/etc/mnt/ikuai/appmarket拷贝environment和default_env |

#### Docker容器（type=1）管理

| 函数名 | 行号 | 功能 |
|--------|------|------|
| `__container_app_init()` | 242 | 先stop再start |
| `__container_app_start()` | 264 | 检查compose.yaml → 生成容器名 → 检查端口 → docker-compose up -d |
| `__container_app_stop()` | 252 | docker-compose down |
| `__container_app_install()` | 291 | 检查compose.yaml → 生成容器名 → 检查端口 → docker-compose up -d |
| `__container_app_uninstall()` | 322 | docker-compose down |
| `__check_compose_yaml()` | 178 | 调用docker_security_checker.lua检查compose文件安全性 |
| `__gen_container_name()` | 186 | 从.env读取NAME_NONCE，生成容器名，处理IMAGE_VERSION |
| `__is_port_in_use()` | 852 | 分析compose端口并检查冲突 |

#### 安装/更新/卸载

| 函数名 | 行号 | 功能 |
|--------|------|------|
| `install()` | 1054 | 主入口：参数检查 → 从apptmp.db查应用信息 → 检查磁盘/内存 → 计算安装路径 → `__pre_app_install` → `__app_install` |
| `install_file()` | 1161 | 离线安装：从IKREST_SESSION读取上传的包 → 解析manifest.json → 调用install |
| `__app_install()` | 910 | 核心安装：执行包下载 → 镜像下载 → 配置恢复 → 写DB → 启动应用 |
| `__app_update()` | 866 | 配置备份 → 包下载 → 镜像下载 → 配置恢复 → 更新DB → 启动 |
| `uninstall()` | 1273 | 从DB读应用信息 → 执行uninstall → 删除DB记录 → 通知云端 |
| `update_app()` | 1310 | 比较版本 → 调用`__app_update` |
| `retry()` | 1262 | 重试安装（queue=1） |
| `delete_file()` | 1128 | 删除上传的临时文件 |

#### 包下载与镜像处理

| 函数名 | 行号 | 功能 |
|--------|------|------|
| `__exec_pkg_download()` | 626 | 下载tar.gz包（或从离线文件拷贝）→ MD5校验 → 解压 → 链接config/data/cache/ui |
| `__exec_img_download()` | 759 | Docker类型：从docker_image.tar.gz加载或docker-compose pull |
| `docker_pull_image()` | 694 | docker-compose pull，记录成功/失败标志文件 |
| `docker_wait_image()` | 708 | 等待pull完成，模拟进度条 |
| `__exec_config_backup()` | 796 | 备份config/data和版本号 |
| `__exec_config_restore()` | 822 | 恢复config/data（版本不回退） |

#### 队列管理

| 函数名 | 行号 | 功能 |
|--------|------|------|
| `__pre_app_install()` | 1012 | 创建目录结构 → 初始化process → 检查队列 → 更新队列状态为running |
| `__add_app_queue()` | 1645 | 调用task_queue.sh添加任务 |
| `__finish_app_queue()` | 1658 | 标记任务完成 |
| `__exec_app_queue()` | 1666 | 清理task_id/pid，触发队列下一个任务 |
| `__update_app_queue_err()` | 1680 | 标记错误退出，发消息通知，触发下一个 |
| `__update_app_queue_run()` | 1688 | 更新任务状态为运行中 |
| `__get_queue_status()` | 1673 | 查询当前任务状态 |

#### 状态/日志/配置

| 函数名 | 行号 | 功能 |
|--------|------|------|
| `__init_process()` | 599 | 初始化安装日志，生成task_id |
| `__update_process()` | 580 | 更新安装状态码和日志 |
| `__update_run_log()` | 572 | 更新运行状态码和日志 |
| `down()` | 1522 | 禁用应用（enabled=no）并停止 |
| `up()` | 1545 | 启用应用（enabled=yes）并启动 |
| `update_config()` | 1409 | 更新应用环境变量配置（CPUS_LIMIT/MEMORY_LIMIT/RESTART/HOST_IP等） |
| `update_stars()` | 1354 | 更新点赞状态 |
| `add_ignore_list()` / `del_ignore_list()` | 1596/1604 | 忽略更新 |
| `app_cache_clean()` | 1572 | 清理应用缓存 |

#### 数据展示（SQL注入）

| 函数名 | 行号 | 功能 |
|--------|------|------|
| `__implant_code()` | 1704 | 核心技巧：生成Lua代码字符串，在SQLite中创建自定义函数（is_installed/has_newversion/is_enabled/status/run_status等），实现动态查询 |
| `__apps_implant_code()` | 1956 | 同上，从缓存文件读取已安装应用状态 |
| `__queue_implant_code()` | 2271 | 为队列查询创建status/message函数 |
| `show()` | 2305 | 主展示入口 |
| `__show_apps_data()` | 2313 | 展示应用商店列表（从apptmp.db） |
| `__show_data()` | 2356 | 展示已安装应用详情 |
| `__show_apps_queue()` | 2339 | 展示安装队列 |
| `__show_config()` | 2657 | 展示应用配置 |
| `__show_login_uri()` | 2368 | 展示应用登录URL |

### 2.4 AppMarket设备端启动流程

```mermaid
flowchart TD
    A["rc脚本 boot_load_async appmarket.sh"] --> B["boot()"]
    B --> C["创建目录结构"]
    B --> D["初始化 apptmp.db"]
    B --> E["clean_upload_cache()"]
    B --> F["init()"]
    F --> G["从 appmarket.db 读已安装列表"]
    G --> H["遍历每个应用 → __exec_rule_init()"]
    H --> I{"type?"}
    I -->|"type=0 原生"| J["__native_app_init()"]
    I -->|"type=1 Docker"| K["__container_app_init()"]
    J --> L["__native_app_verify_integrity()"]
    L --> M["__gen_native_config()"]
    M --> N["执行 start.sh"]
    K --> O["__check_compose_yaml()"]
    O --> P["__gen_container_name()"]
    P --> Q["__is_port_in_use()"]
    Q --> R["docker-compose up -d"]
    B --> S["sync_apps() 异步"]
    S --> T["applist_control.lua → app_get"]
    T --> U["plugin.ikuai8.com /api/v1/device/plugins"]
    U --> V["更新 apptmp.db"]
```

### 2.5 Lua通信层（applist_control.lua）

**云端API地址**: `http://plugin.ikuai8.com`

**认证**: `sign = md5("gwid={gwid}&key=2hfISkJygpsQoQ3QXRbeBvEDDi7pJs7G&lang={lang}&timestamp={ts}")`

| 函数 | 功能 |
|------|------|
| `app_get` | GET `/api/v1/device/plugins` — 拉取应用列表，更新apptmp.db |
| `app_stars` | POST `/api/v1/device/plugins/star` — 点赞/取消点赞 |
| `app_install` | POST `/api/v1/device/plugins/install` — 通知云端安装事件 |
| `app_uninstall` | POST `/api/v1/device/plugins/uninstall` — 通知云端卸载事件 |
| `app_download` | 从阿里云OSS下载tar.gz包 |
| `app_download_direct` | 从apptmp.db读location字段，RC4解密后下载 |
| `get_download_url` | RC4解密location字段得到真实下载URL |
| `apptmpdb_update` | 更新临时数据库，按架构过滤（type=0/1） |

**下载URL解密**: location字段是十六进制字符串，用RC4（key=`V5LiA5LiL5LiN6KaB6Kej5Y6L`）解密。

### 2.6 目录结构

```
/etc/mnt/ikuai/appmarket.db        — 主数据库（已安装应用）
/tmp/iktmp/appmarket/apptmp.db     — 临时数据库（应用商店列表）
/var/appmarket/{name}              — 应用软链接目录
/etc/mnt/ikuai/appmarket/{name}/   — 应用持久配置（environment/default_env）
/etc/disk_user/{disk}/apps/{name}/ — Docker应用存储
/etc/log/apps/{name}/              — 原生应用存储（系统盘）
/usr/ikuai/www/static/appmarket/   — Web UI静态资源
/etc/ssl/default/appmarket_plugin_sign_public.pem — 签名验证公钥
```

---

## 3. PMD设备端完整架构

### 3.1 源码文件

| 文件 | 行数 | 功能 |
|------|------|------|
| `main.c` | 313 | 程序入口、信号处理、初始化、bootup_restore |
| `routine.c` | 1400 | 核心运行循环、服务端通信、login/query/report |
| `package.c` | 1049 | 包下载、AES解密、安装/卸载脚本执行 |
| `db.c` | 424 | AES加密JSON数据库（.__DB文件） |
| `monitor.c` | 220 | 进程监控、异常重启 |
| `update_msg.c` | 302 | 通信协议序列化/反序列化 |
| `basic.c` | 731 | 系统信息采集（base64/crc32/md5/aes等工具） |
| `aes.c` | 228 | AES-256-CBC加解密实现 |
| `list.h` / `list_sort.c` | 502/251 | 通用链表+排序 |

### 3.2 main.c — 入口与初始化

```mermaid
flowchart TD
    A["main()"] --> B["setofflog() 初始化日志（延迟到init真正设置）"]
    A --> C["命令行解析（-v版本 -L列表 -m检查命令 -s服务器 -l日志级别 -d调试）"]
    C --> D{"调试模式?"}
    D -->|"否"| E["daemon(0,0) 转守护进程"]
    D -->|"是"| F["跳过"]
    E --> G["create_pidfile() 创建/var/run/pmd.pid（文件锁）"]
    F --> G
    G --> H["init()"]
    H --> I["recursive_mkdir('/tmp/log/pmd') 创建日志目录"]
    H --> J["init_log() 初始化日志"]
    H --> K["gather_sys_info() 采集系统信息（GWID/固件版本/CPU架构/磁盘/内存）"]
    H --> L["init_server_list() 从/etc/pmd.d/pmd_host读取服务器列表"]
    H --> M["信号注册：SIGHUP=notify_query, SIGUSR1=reload_binary, SIGUSR2=reload_host, SIGTERM=shutdown"]
    H --> N["curl_global_init()"]
    H --> O["set_update_proto() 设置AES加密key/iv（硬编码在key_lookup/iv_lookup函数中）"]
    H --> P["pkgdb_init() 初始化AES加密数据库"]
    H --> Q["backup_argv_list() 保存argv（用于self-reload）"]
    Q --> R["bootup_restore() 加载数据库 → 重装所有已记录的包"]
    R --> S["login() 连接服务端登录"]
    S --> T["mainloop() 主循环"]
```

**关键设计**: `set_update_proto()` 中的AES key/iv不是静态字符串，而是通过switch-case函数（key_lookup/iv_lookup）逐字符构建，避免在ELF数据段中被静态分析发现。

### 3.3 routine.c — 核心运行循环

#### 全局状态

```c
volatile bool running;              // 主循环运行标志
volatile bool flags_reload_host;    // SIGUSR2: 重新加载服务器列表
volatile bool flags_reload_binary;  // SIGUSR1: 重新加载自身二进制
volatile bool flags_notify_query;   // SIGHUP: 立即查询
```

#### 服务器连接

- 默认服务器: `pkgmanager.ikuai8.com:1863`, `:15602`
- 配置文件: `/etc/pmd.d/pmd_host`
- 支持多服务器轮换（change_server_node）
- 支持DNS解析（ik_dns脚本）
- OEM模式: `127.0.0.1:1863`

#### login() — 登录流程

```mermaid
flowchart TD
    A["login()"] --> B{"循环直到成功"}
    B --> C["conn_server() TCP连接"]
    B --> D["构建login请求"]
    D --> E["basic_info: enterprise/oem_name/firmware/version/gwid"]
    D --> F["packages_list: 当前已安装包列表（name+version）"]
    B --> G["send_update_msg() AES加密后发送"]
    B --> H["recv_update_msg() 接收并解密响应"]
    B --> I["process_task(resp.data) 处理服务端指令"]
    B --> J{"失败?"}
    J -->|"是"| K["sleep → change_server_node → 重试"]
    J -->|"否"| L["登录成功"]
```

#### query() — 定期查询

```mermaid
flowchart TD
    A["query()"] --> B["conn_server()"]
    B --> C["构建query请求（当前已安装包列表）"]
    C --> D["send/recv"]
    D --> E["process_task(resp.data)"]
```

#### process_task() — 处理服务端指令

```mermaid
flowchart TD
    A["process_task(resp_data)"] --> B["解析 next_query 更新查询间隔"]
    A --> C["处理 packages_uninstall_list"]
    C --> D["对每个包: 查DB → 移除监控 → package_uninstall() → 记录结果"]
    A --> E["处理 packages_list（安装/更新）"]
    E --> F["对每个包: package_install()"]
    F --> G{"成功?"}
    G -->|"是"| H["添加监控 → 清理旧版本文件 → 更新DB"]
    G -->|"否"| I["记录错误信息"]
    H --> J["report() 上报安装/卸载结果（最多重试5次）"]
    I --> J
```

#### mainloop() — 主循环

```mermaid
flowchart TD
    A["mainloop()"] --> B{"while(running)"}
    B --> C["sleep(1), g_next_query_wait_sec--"]
    B --> D{"flags_reload_host?"}
    D -->|"是"| E["do_reload_host()"]
    B --> F{"定期query 或 flags_notify_query?"}
    F -->|"是"| G["do_trival_task() 更新磁盘/内存信息"]
    G --> H["query()"]
    B --> I{"flags_reload_binary?"}
    I -->|"是"| J["do_reload() fork+execvp自我重启"]
    B --> K{"每60秒?"}
    K -->|"是"| L["probe_all_process() 进程监控"]
    B --> M["cleanup()"]
```

### 3.4 package.c — 包管理

#### 包安装流程

```mermaid
flowchart TD
    A["package_install(entry, res_info)"] --> B["版本检查"]
    B --> C["执行 entry-ver_method 获取当前版本"]
    B --> D["package_upgrade_check() 比较"]
    D --> E["greater: 数字比较"]
    D --> F["noequal: 字符串比较"]
    B --> G{"当前版本 = 新版本?"}
    G -->|"是"| H["返回 E_VERSION"]
    G -->|"否"| I["查找本地包文件"]
    I --> J["package_locate_file() 在primary/alternative目录查找.bin.pkg"]
    J --> K{"找到?"}
    K -->|"否"| L["package_download() 从URL下载"]
    K -->|"是"| M["磁盘空间检查 → 内存检查"]
    L --> M
    M --> N{"需要下载?"}
    N -->|"是"| O["package_cur_save_dir() 选择存储目录"]
    O --> P["fetch_file_with_http() curl下载, MD5校验, 断点续传（最多3次）"]
    P --> Q["md5file() 下载后MD5验证"]
    N -->|"否"| R["跳过下载"]
    Q --> S{"有secret_key?"}
    R --> S
    S -->|"是"| T["decrypt_file() AES-128-CBC 或 AES-256-CBC"]
    T --> U["输出 /tmp/__package_{name}.sh"]
    S -->|"否"| V["跳过解密"]
    U --> W["bash (outfile) install（超时600秒）"]
    V --> W
    W --> X["返回结果"]
```

#### 包卸载流程

```mermaid
flowchart TD
    A["package_uninstall(entry, res_info)"] --> B["pkgdb_query() 从DB查包信息"]
    B --> C["create_install_entry() 重建安装条目"]
    C --> D["package_locate_file() 定位.bin.pkg文件"]
    D --> E{"有secret_key?"}
    E -->|"是"| F["AES解密"]
    E -->|"否"| G["跳过解密"]
    F --> H["bash (outfile) uninstall（超时600秒）"]
    G --> H
    H --> I["pkgdb_remove() 从DB删除"]
    I --> J["package_remove() 删除.bin.pkg文件"]
```

#### 包文件命名

- 包文件: `{name}.bin.pkg`
- 解密后文件: `/tmp/__package_{name}.sh`
- 安装命令: `bash {file} install`
- 卸载命令: `bash {file} uninstall`

### 3.5 db.c — AES加密JSON数据库

**设计原则（代码注释）**：
- PMD需要保证断网后设备重启仍能恢复已安装软件
- /etc/log是唯一可持久化的磁盘，但文件系统稳定性差
- 策略：先写/tmp/（几乎不会失败），再同步到/etc/log/

**数据库文件**：

```
路径: /etc/log/store/info/.__DB.{version_first_char}.{arch}{oem_suffix}
临时: /tmp/iktmp/db/.__DB.{version_first_char}.{arch}{oem_suffix}
```

**加密**: AES-256-CBC，key/iv通过`code_string()`从整数索引数组构建。

**数据格式**: JSON数组，每个元素包含：

```json
{
  "name": "ik_rc_client",
  "priority": 10,
  "version": "2019112614",
  "ver_method": "ik_rc_client -v",
  "ver_cmp": "greater",
  "download": ["https://...", "http://..."],
  "md5": "384a8479...",
  "encryption": "aes-256-cbc",
  "secret_key": "cdn.ik.com",
  "monitor_cmd": "...",
  "monitor_startup_cmd": ["..."]
}
```

### 3.6 monitor.c — 进程监控

```mermaid
flowchart TD
    A["probe_all_process()（每60秒）"] --> B["遍历所有监控进程"]
    B --> C{"启动10秒内?"}
    C -->|"是"| D["跳过"]
    C -->|"否"| E["check_process_exist(monitor_cmd)"]
    E --> F["执行monitor_cmd（如 ps /grep xxx /grep -v）"]
    F --> G{"输出为空?"}
    G -->|"是（进程不存在）"| H["process_exit_handler()"]
    G -->|"否"| I["正常"]
    H --> J["launch() 执行monitor_startup_cmd重启进程"]
    H --> K["count++"]
    H --> L{"count>=3 或 距上次>=300秒?"}
    L -->|"是"| M["handler() → report_restart_evt() 上报服务端"]
    L -->|"否"| N["等待下次检查"]
```

### 3.7 update_msg.c — 通信协议

**协议格式（ikstd_prot）**：

```
Header (20字节):
  ver(1) | dType(1) | enType(1) | mType(1) | msn(4) | reserved(4) | data_len(4) | checksum(4)

Body:
  enType=0: 明文JSON
  enType=1: AES-256-CBC加密的JSON

mType: 0=请求, 1=响应
```

**消息类型**：
- LOGIN_REQ/RES — 登录
- QUERY_REQ/RES — 查询
- REPORT_REQ/RES — 上报

---

## 4. PMD服务端（ik_rc）完整架构

### 4.1 源码文件

| 文件 | 行数 | 功能 |
|------|------|------|
| `ik_rc.c` | 165 | 程序入口、组件初始化 |
| `rest.c` | 926 | REST API服务（HTTP） |
| `rpcs.c` | 660 | RPC服务（设备控制通道） |
| `mgnt.c` | 1229 | 核心管理逻辑、AS注册、keepalive |
| `router_list.c` | 157 | 在线/离线路由器列表管理 |
| `proc.c` | 143 | CPU/内存采样 |
| `task.c` | 246 | 任务字典（gwid → task列表） |
| `rpc_http_parser.c` | 171 | RPC HTTP请求解析 |
| `http_server.c` | 543 | HTTP服务器（libevent） |
| `http_parser.c` | 2501 | HTTP协议解析器 |

### 4.2 ik_rc.c — 入口与初始化

```mermaid
flowchart TD
    A["main()"] --> B["parse_main_args() 解析命令行"]
    B --> C["init_env() 初始化日志、curl、信号"]
    C --> D["rcs_mgnt_new() 创建管理器"]
    D --> E["创建hub_list（N个libevent线程）"]
    D --> F["创建online/offline router列表"]
    D --> G["创建token列表"]
    D --> H["设置回调：client_action/ctrl_resp/session_end"]
    C --> I["rcs_mgnt_set_as_master() 设置AS主节点"]
    C --> J["rcs_rest_new() 创建REST API服务"]
    C --> K["rpc_srv_new() 创建RPC控制服务"]
    C --> L["rcs_rest_start() 启动REST（先于mgnt）"]
    L --> M["rcs_mgnt_start() 启动管理器"]
    M --> N["启动hub线程"]
    M --> O["向AS注册"]
    M --> P["启动keepalive线程"]
    M --> Q["启动backend线程"]
    M --> R["rpc_srv_start() 启动RPC"]
    R --> S["rcs_mgnt_wait() 等待退出"]
```

### 4.3 mgnt.c — 核心管理

#### AS注册

```mermaid
flowchart TD
    A["rcs_mgnt_register_self(mgnt)"] --> B["POST /rcs/(service_name) 到AS"]
    B --> C["提交: name_id, rest_host, rest_port"]
    B --> D["提交: rc_host, rc_port"]
    B --> E["提交: ctrl_host, ctrl_port"]
    B --> F["提交: weight, version"]
    B --> G["解析AS响应"]
    G --> H["report_interval — keepalive间隔"]
    G --> I["master — AS主节点（host/port/name_id）"]
    G --> J["slave — AS备节点（可选）"]
```

#### 设备上线/下线

```mermaid
flowchart TD
    A["client_action_handler(act, hub, gwid)"] --> B{"act = true?"}
    B -->|"上线"| C["POST /rcs/(srv)/routers/(gwid) 到AS"]
    C --> D{"AS返回200?"}
    D -->|"是"| E["加入online_routers"]
    D -->|"否"| F["通知路由器断开"]
    B -->|"下线"| G["从online_routers移到offline_routers"]
    G --> H["关闭RPC session"]
    G --> I["DELETE /rcs/(srv)/routers/(gwid) 到AS"]
```

#### 任务转发

```mermaid
flowchart TD
    A["rcs_mgnt_fwd_ctrl(mgnt, gwid, sid, buf, len)"] --> B["router_list_find(online_routers, gwid)"]
    B --> C["rchub_send_rc_ctrl_req(hub, gwid, buf, len, sid)"]
    C --> D["router-fwding = true"]
```

#### Keepalive

```mermaid
flowchart TD
    A["keepalive_thread_routine()"] --> B["每(keepalive_intvl)秒"]
    B --> C["POST /rcs/(srv)/status 到AS"]
    C --> D["提交: state(running/exiting)"]
    C --> E["提交: client_number"]
    C --> F["提交: cpu, mem"]
    B --> G["解析响应: 更新report_interval, master/slave"]
```

### 4.4 rest.c — REST API

| 路径 | 方法 | 功能 |
|------|------|------|
| `/service` | GET | 获取RC服务信息 |
| `/service` | POST | 更新weight/as_master |
| `/service` | DELETE | 停止RC服务 |
| `/log` | POST | 设置日志级别/大小 |
| `/status` | GET | 获取运行状态（客户端数/CPU/内存） |
| `/version` | GET | 获取版本信息 |
| `/sessions/{gwid}` | POST | 创建会话（token+key+expired） |
| `/sessions/{gwid}` | GET | 获取会话信息 |
| `/sessions/{gwid}` | DELETE | 删除会话 |
| `/routers/{gwid}` | GET | 获取在线路由器信息 |

### 4.5 rpcs.c — RPC控制通道

- 基于libevent的TCP服务
- 设备通过 `GET /router/{gwid}/d` 建立长连接
- 支持session管理和超时关闭
- 任务通过 `rchub_send_rc_ctrl_req` 下发到设备
- 设备响应通过 `ctrl_resp_handler` 回调处理

### 4.6 task.c — 任务管理

- 以gwid为键的Hash表
- 每个gwid下有任务链表
- 10分钟自动清理过期任务
- 支持按fd批量清理

---

## 5. ipkg包格式+签名验证流程

### 5.1 ipkg包文件结构

```
{name}-{version}-{arch}.ipkg    （架构包，arch = amd64/arm64）
{name}-{version}.ipkg           （通用包，无arch字段）

包内容（tar.gz）:
  manifest.json          — 元数据 + integrity签名信息
  manifest.json.sig      — RSA-3072签名文件
  scripts/
    PRE_INST.sh          — 安装前脚本
    start.sh             — 启动脚本
    stop.sh              — 停止脚本
    POST_INST.sh         — 安装后脚本
    PRE_UNINST.sh        — 卸载前脚本
    POST_UNINST.sh       — 卸载后脚本
  app/
    bin/                 — 二进制文件（参与签名校验）
    config/              — 配置模板
    .env                 — 环境变量模板
  docker-compose.yaml    — Docker类型（type=1）
  ui/                    — Web UI资源（可选）
```

### 5.2 manifest.json 格式（签名后）

```json
{
    "name": "ddns-go",
    "version": "6.17.1",
    "display_name": "ddns-go",
    "type": "0",
    "integrity": {
        "algorithm": "sha256",
        "signature_algorithm": "rsa-3072-sha256",
        "signature_file": "manifest.json.sig",
        "files": [
            {"path": "scripts/start.sh", "sha256": "abc123..."},
            {"path": "app/bin/ddns-go", "sha256": "def456..."}
        ]
    }
}
```

### 5.3 签名流程（服务端 sign_app_manifest.sh）

```mermaid
flowchart TD
    A["sign_app_manifest.sh"] --> B["扫描 scripts/ 和 app/bin/ 目录"]
    B --> C["对每个文件计算 SHA-256"]
    C --> D["生成 files.json: [{path, sha256}, ...]"]
    D --> E["更新 manifest.json，写入 integrity 字段"]
    E --> F["openssl dgst -sha256 -sign private_key → manifest.json.sig"]
    F --> G["用 public_key 验证签名"]
    G --> H["逐文件验证 SHA-256 一致性"]
    G --> I["打包 tar.gz → {name}-{version}-{arch}.ipkg"]
```

### 5.4 验证流程（设备端 __native_app_verify_integrity）

```mermaid
flowchart TD
    A["__native_app_verify_integrity()"] --> B["检查 manifest.json 存在"]
    B --> C["检查 jq/openssl/sha256sum 命令可用"]
    C --> D["检查公钥文件<br/>/etc/ssl/default/appmarket_plugin_sign_public.pem"]
    D --> E["从manifest.json读取 integrity.signature_file<br/>（默认 manifest.json.sig）"]
    E --> F["openssl dgst -sha256 -verify public_key<br/>-signature sig_file manifest.json"]
    F --> G{"签名验证通过?"}
    G -->|"否"| H["返回失败"]
    G -->|"是"| I["遍历 integrity.files[]"]
    I --> J["路径安全检查（只允许 scripts/* 和 app/bin/*）"]
    J --> K["SHA-256格式检查（64位hex）"]
    K --> L["计算实际SHA-256"]
    L --> M["比对声明值"]
    M --> N{"全部匹配?"}
    N -->|"否"| O["返回失败"]
    N -->|"是"| P["验证通过"]
```

### 5.5 包验证流程（validate_native_app_identities.sh）

```mermaid
flowchart TD
    A["validate_native_app_identities.sh"] --> B["遍历 native-apps/ 下所有目录"]
    B --> C["检查 manifest.name 不为空"]
    C --> D["检查 name 不含架构后缀（-amd64/-arm64）"]
    D --> E["检查目录名 == manifest.name"]
    E --> F["检查 app/bin/ 目录存在"]
    F --> G["检查无 .gitkeep 文件"]
    G --> H["对 .ipkg 包验证"]
    H --> I["解压检查 root == manifest.name"]
    I --> J["检查文件名格式"]
    J --> K["架构包: {name}-{version}-{arch}.ipkg"]
    J --> L["通用包: {name}-{version}.ipkg（无arch字段）"]
```

---

## 6. PMD包格式+AES加密流程

### 6.1 包格式

```
{name}.bin.pkg  ← AES-256-CBC加密的shell脚本
```

解密后是一个shell脚本，接受 `install` / `uninstall` 参数。

### 6.2 安装条目JSON结构（服务端下发）

```json
{
    "name": "ik_rc_client",
    "version": "2019112614",
    "ver_method": "ik_rc_client -v",
    "ver_cmp": "greater",
    "priority": 10,
    "download": [
        "https://packages.ikuai8.com/.../ik_rc_client_bin_2019112614.x86.release.install",
        "http://packages.ikuai8.com/.../ik_rc_client_bin_2019112614.x86.release.install"
    ],
    "md5": "384a8479da4d2cc5361d76f596833f63",
    "encryption": "aes-256-cbc",
    "secret_key": "cdn.ik.com",
    "secret_iv": "...",
    "minimum_size": 5000,
    "timeout_per_request": 300,
    "monitor_cmd": "ps |grep ik_rc_client|grep -v",
    "monitor_startup_cmd": "ik_rc_client"
}
```

### 6.3 加密/解密流程

```mermaid
flowchart TD
    subgraph Server["服务端（构建阶段）"]
        S1["编写安装shell脚本"] --> S2["AES-256-CBC加密<br/>key=secret_key, iv=secret_iv"]
        S2 --> S3["输出 {name}.bin.pkg"]
        S3 --> S4["计算MD5"]
        S4 --> S5["上传到CDN<br/>packages.ikuai8.com"]
        S5 --> S6["下发install entry JSON到设备"]
    end
    subgraph Device["设备端（package.c）"]
        D1["收到 install 指令"] --> D2["package_download()<br/>curl下载 .bin.pkg"]
        D2 --> D3["md5file() MD5校验完整性"]
        D3 --> D4{"有 encryption 字段?"}
        D4 -->|"是"| D5["decrypt_file()<br/>AES-256-CBC 解密"]
        D4 -->|"否"| D6["跳过解密"]
        D5 --> D7["输出 /tmp/__package_{name}.sh"]
        D6 --> D7
        D7 --> D8["bash /tmp/__package_{name}.sh install<br/>（超时600秒）"]
        D8 --> D9["返回结果"]
    end
    S6 --> D1
```

### 6.4 数据库加密（db.c）

```mermaid
flowchart LR
    A["pkgdb_init()"] --> B["code_string()<br/>从整数索引数组构建key/iv"]
    B --> C["AES-256-CBC"]
    C --> D["写 /tmp/iktmp/db/.__DB（临时）"]
    D --> E["同步到 /etc/log/store/info/.__DB（持久）"]
```

### 6.5 通信协议加密（update_msg.c）

```mermaid
flowchart LR
    A["set_update_proto()"] --> B["key_lookup() 32字节key<br/>逐字符构建"]
    A --> C["iv_lookup() 16字节iv<br/>逐字符构建"]
    B --> D["AES-256-CBC 加密/解密"]
    C --> D
    D --> E["ikstd_prot 协议Body"]
```

---

## 7. OSPF当前固化方式

### 7.1 源文件

| 文件 | 行数 | 功能 |
|------|------|------|
| `script/ospf.sh` | 5062 | OSPF主脚本（初始化/增删改/重载） |
| `function/ospf` | 5062 | OSPF功能函数库（与ospf.sh相同） |
| `frr-reload-c/src/frr-reload.c` | 3263 | FRR配置热重载工具（C实现） |

### 7.2 固化方式分析

OSPF **完全固化在固件中**，不是通过ipkg/pmd安装的：

1. **FRR二进制**: `/usr/sbin/fq/` 目录下（zebra/ospfd/ospf6d/staticd/watchfrr/vtysh/frr-reload）
2. **配置文件**: `/etc/fq/frr/frr.conf`（运行时生成）, `/etc/fq/frr/daemons`（守护进程开关）
3. **启动脚本**: rc脚本中 `boot_load_sync ospf.sh`（同步启动，在最后面）
4. **数据库**: `ospf_*` 表在主配置数据库 `$IK_DB_CONFIG` 中

### 7.3 ospf.sh 核心流程

```mermaid
flowchart TD
    A["__init()"] --> B["__sync_business_interface_if_needed() 同步业务接口"]
    A --> C["__sync_static_route_if_needed() 同步静态路由"]
    A --> D["生成FRR配置"]
    D --> E["__emit_basic() 基础配置"]
    D --> F["__emit_log_target() 日志目标"]
    D --> G["__emit_debug_flag() 调试标志"]
    D --> H["__emit_prefix_list() 前缀列表"]
    D --> I["__emit_default_block_route_map() 默认阻断路由图"]
    D --> J["__emit_static_route() 静态路由"]
    D --> K["__emit_interface() 接口配置"]
    D --> L["__emit_instance() OSPF实例配置"]
    D --> M["__emit_vty_line() VTY线路配置"]
    D --> N["cp $INIT_CONFIG $FRR_CONFIG 写入frr.conf"]
    N --> O["__update_daemons() 更新daemons文件"]
    O --> P["__sync_ospf_packet_rule() 同步iptables OSPF规则"]
    P --> Q["__clean_kernel_static_route_if_needed() 清理内核静态路由"]
    Q --> R["启动/重载"]
    R --> S{"has_frr_reload 且 has_running_frr_daemon?"}
    S -->|"是"| T["__run_frr_reload() 热重载（不重启watchfrr）"]
    S -->|"否"| U["__start_watchfrr() 冷启动"]
```

**add/del/set_enabled/reconf** 操作：
- 修改SQLite中的 `ospf_*` 表
- 调用 `__reload_frr()` 重新生成配置并热重载

### 7.4 frr-reload.c

C实现的FRR配置热重载工具，替代Python版frr-reload.py：
- 比较目标配置与运行配置
- 通过vtysh应用增量变更
- 仅在daemon列表变化时重启watchfrr

---

## 8. rc启动顺序

### 8.1 rc脚本启动顺序

```mermaid
flowchart TD
    A["boot()"] --> B["系统环境初始化"]
    B --> C["start_ikuai_services()<br/>iktimerd / iksyslogd / openresty 等"]
    C --> D["start_remote_services()"]
    D --> E["ik_rc_client 后台启动<br/>PMD体系：远程控制客户端"]
    D --> F["pmd 后台启动<br/>PMD体系：包管理daemon"]
    D --> G["cre_client（OEM模式）"]
    D --> H["boot_load_async appmarket.sh<br/>AppMarket异步启动"]
    H --> I["... 其他业务脚本 ..."]
    I --> J["boot_load_sync ospf.sh<br/>OSPF同步启动（接近最后）"]
    J --> K["..."]
```

### 8.2 启动顺序分析

1. **PMD先启动**（start_remote_services中，同步）
   - pmd daemon启动后立即连接服务端
   - bootup_restore() 从AES加密DB恢复已安装的包
   - login() 向服务端登录并接收指令

2. **AppMarket后启动**（boot_load_async，异步）
   - boot() 创建目录、初始化临时DB
   - init() 从主DB读已安装应用列表，逐个启动
   - sync_apps() 异步从云端拉取应用列表

3. **OSPF最后启动**（boot_load_sync，同步）
   - 从SQLite读OSPF配置
   - 生成FRR配置
   - 启动/重载FRR daemon

### 8.3 两套体系并存现状

```mermaid
graph LR
    subgraph PMD体系
        P1["设备端: /usr/sbin/pmd<br/>C daemon, 独立运行"]
        P2["服务端: pkgmanager.ikuai8.com:1863<br/>TCP自有协议"]
        P3["管理: 服务端推送<br/>设备端被动执行"]
        P4["无前端"]
        P1 --> P2
        P2 --> P3
        P3 --> P4
    end
    subgraph AppMarket体系
        A1["设备端: function/appmarket<br/>+ applist_control.lua<br/>Shell+Lua"]
        A2["服务端: plugin.ikuai8.com<br/>HTTP REST"]
        A3["管理: 前端触发<br/>Shell执行"]
        A4["有前端"]
        A1 --> A2
        A2 --> A3
        A3 --> A4
    end
```

两套体系完全独立，没有代码层面的交互。PMD管ik_rc_client等二进制工具的安装更新。AppMarket管Docker应用和原生应用（ipkg）的安装更新。

---

## 9. 设备启动数据流

```mermaid
flowchart TD
    A["rc脚本"] --> B["start_remote_services()"]
    B --> C["ik_rc_client 后台启动<br/>PMD: 远程控制客户端"]
    B --> D["pmd 后台启动<br/>PMD: 包管理daemon"]
    D --> E["init()"]
    E --> F["gather_sys_info() 读系统信息"]
    E --> G["init_server_list() 读/etc/pmd.d/pmd_host"]
    E --> H["pkgdb_init() 初始化AES加密DB"]
    H --> I["bootup_restore()"]
    I --> J["pkgdb_load() 读.__DB（AES解密）"]
    J --> K["package_reinstall() 重装所有包"]
    K --> L["bash (pkg) install"]
    D --> M["login() 连接pkgmanager.ikuai8.com:1863"]
    M --> N["process_task() 接收服务端指令"]
    A --> O["boot_load_async appmarket.sh"]
    O --> P["boot()"]
    P --> Q["sqlite3 apptmp.db + apptmp.conf"]
    P --> R["init()"]
    R --> S["sync_apps 后台<br/>Lua拉取云端列表"]
    S --> T["app_get → plugin.ikuai8.com"]
    R --> U["遍历applist → __exec_rule_init"]
    U --> V{"type?"}
    V -->|"type=0"| W["__native_app_start"]
    W --> X["__native_app_verify_integrity<br/>RSA签名验证"]
    X --> Y["scripts/start.sh"]
    V -->|"type=1"| Z["__container_app_start"]
    Z --> AA["docker-compose up -d"]
    P --> AB["__apps_to_cache()<br/>缓存到/tmp/iktmp/appmarket/config"]
    A --> AC["boot_load_sync ospf.sh"]
    AC --> AD["init()"]
    AD --> AE["生成frr.conf ← SQLite ospf_*表"]
    AE --> AF["frr-reload / watchfrr"]
    AF --> AG["运行中"]
    AG --> AH["PMD mainloop()"]
    AH --> AI["每60秒 query() → 服务端推送安装/卸载"]
    AH --> AJ["每60秒 probe_all_process() → 进程重启"]
    AH --> AK["SIGUSR1 → 自我热升级"]
    AG --> AL["AppMarket"]
    AL --> AM["前端操作 → Shell执行<br/>install/uninstall/up/down"]
    AL --> AN["状态查询 → SQLite + Lua注入函数"]
    AG --> AO["OSPF"]
    AO --> AP["前端操作 → add/del → __reload_frr()"]
```

---

## 10. 在线更新数据流

```mermaid
flowchart TD
    subgraph AppMarket在线更新
        A1["查 apptmp.db 获取应用信息"] --> A2["检查磁盘/内存"]
        A2 --> A3["__pre_app_install 加入队列"]
        A3 --> A4["__app_install 异步"]
        A4 --> A5["__exec_pkg_download"]
        A5 --> A6["applist_control.lua<br/>app_download_direct"]
        A6 --> A7["RC4解密URL"]
        A7 --> A8["curl下载 tar.gz"]
        A8 --> A9["MD5校验"]
        A5 --> A10["tar解压"]
        A4 --> A11["__exec_img_download"]
        A11 --> A12["docker-compose pull"]
        A4 --> A13["__exec_config_restore"]
        A4 --> A14["写 appmarket.db"]
        A4 --> A15["__exec_app_install"]
        A15 --> A16{"type?"}
        A16 -->|"type=0"| A17["验证签名 → start.sh"]
        A16 -->|"type=1"| A18["docker-compose up"]
        A4 --> A19["通知云端 app_install"]
    end
    subgraph PMD在线更新
        B1["process_task()"] --> B2["packages_list"]
        B2 --> B3["package_install()"]
        B3 --> B4["版本检查 ver_method"]
        B3 --> B5["package_download curl"]
        B5 --> B6["MD5校验"]
        B3 --> B7["decrypt_file AES解密"]
        B7 --> B8["bash (file) install"]
        B8 --> B9["pkgdb_update AES加密DB"]
        B8 --> B10["add_monitor_process"]
        B8 --> B11["report() → 服务端"]
    end
```

---

## 11. 离线安装数据流

```mermaid
flowchart TD
    A["前端上传文件"] --> B["IKREST_SESSION（会话路径）"]
    B --> C["install_file()"]
    C --> D["读取上传目录下的 manifest.json"]
    D --> E["解析 name/version/type/maintainer 等"]
    E --> F["分配 appid（≥100000）"]
    F --> G{"mode?"}
    G -->|"mode=0 直接安装"| H["install()"]
    G -->|"mode=1 备份后安装（更新）"| I["备份配置"]
    G -->|"mode=2 卸载后安装"| J["先卸载旧版"]
    I --> H
    J --> H
    H --> K["filepkg = 上传路径（跳过下载）"]
    K --> L["__exec_pkg_download 从filepkg拷贝"]
    L --> M["MD5校验 → tar解压 → 链接config/data/cache/ui"]
    M --> N["__exec_config_restore"]
    N --> O["写 appmarket.db"]
    O --> P["__exec_app_install"]
    P --> Q{"type?"}
    Q -->|"type=0"| R["验证签名 → start.sh"]
    Q -->|"type=1"| S["docker-compose up -d"]
    R --> T["通知云端 app_install"]
    S --> T
```

> 注意：PMD体系不支持离线安装，只能由服务端推送。

---

## 12. 进程监控对比

```mermaid
flowchart TD
    subgraph AppMarket监控
        A1["被动检查"] --> A2["依靠 run.status 文件<br/>（0=成功, 1=启动, -1=失败）"]
        A2 --> A3["is_enabled() Lua函数检查"]
        A3 --> A4["enabled=yes 且 run_status==0"]
        A4 --> A5["docker容器运行状态"]
        A5 --> A6["前端查询时才发现异常"]
        A6 --> A7["无自动重启"]
    end
    subgraph PMD监控
        B1["主动监控"] --> B2["probe_all_process() 每60秒"]
        B2 --> B3["遍历 process_list"]
        B3 --> B4["跳过启动10秒内的进程"]
        B4 --> B5["check_process_exist(monitor_cmd)"]
        B5 --> B6["ik_execute_cmd('ps /grep xxx')"]
        B6 --> B7{"进程不存在?"}
        B7 -->|"是"| B8["launch() 自动重启"]
        B8 --> B9["count++"]
        B9 --> B10{"count>=3 或 300秒?"}
        B10 -->|"是"| B11["report_restart_evt 上报服务端"]
        B7 -->|"否"| B12["正常"]
    end
```

### 监控能力对比

| 能力 | AppMarket | PMD |
|------|-----------|-----|
| 检查方式 | 被动（前端查询时） | 主动（每60秒轮询） |
| 依赖 | run.status文件 + Lua函数 | C daemon + ps/grep |
| 自动重启 | 无 | 有（monitor_startup_cmd） |
| 异常上报 | 无 | 有（report_restart_evt） |
| 重启限制 | 无 | count>=3 或 300秒间隔上报 |
| Docker支持 | 有 | 无 |

---

## 13. 两套体系对接点分析

### 13.1 当前对接点

**几乎没有直接对接**。两套体系各自独立运行：

| 方面 | AppMarket | PMD | 对接 |
|------|-----------|-----|------|
| 数据库 | SQLite | AES-JSON | 无 |
| 服务端 | plugin.ikuai8.com | pkgmanager.ikuai8.com:1863 | 无 |
| 包格式 | tar.gz | .bin.pkg | 无 |
| 安装路径 | /etc/log/apps/ 或 /etc/disk_user/.../apps/ | /etc/log/packages/ 或 /tmp/packages/ | 无 |
| 进程管理 | Shell函数 | C daemon | 无 |
| 前端 | 有 | 无 | PMD无前端 |

### 13.2 潜在对接点

#### A. 安装路径可统一

- AppMarket原生应用: `/etc/log/apps/{name}/`（系统盘）或 `/etc/disk_user/{disk}/apps/{name}/`
- PMD包: `/etc/log/packages/` 或 `/tmp/packages/`
- 建议: 统一到 `/etc/log/apps/{name}/` 或 `/var/appmarket/{name}/`

#### B. 进程监控可统一

- AppMarket的 `run.status` 文件方式简陋且被动
- PMD的 `monitor.c` 主动轮询+自动重启+上报 更完善
- 建议: 统一使用PMD的主动监控方式

#### C. 签名验证可统一

- AppMarket已有RSA-3072签名验证（公钥在固件中）
- PMD仅AES加密，无签名验证
- 建议: PMD包也增加签名验证

#### D. 数据库可统一

- AppMarket: SQLite（结构化，可查询，有Lua注入函数）
- PMD: AES加密JSON（简单，但不可查询）
- 建议: 统一到SQLite

#### E. 通信协议可统一

- AppMarket: HTTP REST（标准，易调试）
- PMD: 自有TCP协议（复杂，但支持推送）
- 建议: 保留PMD的推送能力，但改用HTTP(S)长轮询或WebSocket

#### F. 应用类型可统一

- AppMarket type=0（原生应用）≈ PMD管理的二进制包
- AppMarket type=1（Docker）— PMD不支持
- 建议: 统一type定义，PMD负责type=0，Docker由AppMarket或统一框架管理

---

## 14. 接口设计建议

### 14.1 统一后端架构建议

```mermaid
graph TB
    subgraph 前端
        UI["Web UI（统一界面）"]
    end
    subgraph 服务端
        API["统一API网关<br/>HTTP REST + SSE推送"]
        STORE["包仓库<br/>统一ipkg格式 + RSA签名"]
        DB_S["设备状态DB<br/>gwid → 应用列表/状态"]
    end
    subgraph 设备端
        DAEMON["统一daemon<br/>安装/卸载/监控"]
        LOCAL_DB["SQLite本地DB<br/>（替代AES JSON DB）"]
        VERIFY["签名验证模块<br/>RSA-3072 + SHA-256"]
        MONITOR["进程监控模块<br/>主动轮询 + 自动重启"]
    end
    UI --> API
    API --> STORE
    API --> DB_S
    API -->|SSE推送| DAEMON
    DAEMON --> LOCAL_DB
    DAEMON --> VERIFY
    DAEMON --> MONITOR
    STORE -->|下载ipkg| DAEMON
```

### 14.2 统一包格式建议

保留ipkg格式，废弃.bin.pkg：

```
manifest.json          — 元数据 + integrity签名
manifest.json.sig      — RSA-3072签名
scripts/
  PRE_INST.sh          — 安装前
  start.sh             — 启动
  stop.sh              — 停止
  POST_INST.sh         — 安装后
  PRE_UNINST.sh        — 卸载前
  POST_UNINST.sh       — 卸载后
app/
  bin/                 — 二进制文件（参与签名校验）
  config/              — 配置模板
  .env                 — 环境变量模板
docker-compose.yaml    — Docker类型
ui/                    — Web UI资源（可选）
monitor.json           — 监控配置（新增）
options.json           — 前端配置项（可选）
```

**manifest.json 统一字段**：

```json
{
    "name": "xxx",
    "version": "1.0.0",
    "display_name": "XXX",
    "description": "...",
    "type": "native|docker",
    "maintainer": "...",
    "maintainer_url": "...",
    "distributor": "...",
    "distributor_url": "...",
    "requirements": {
        "memory": "128MB",
        "storage": "64MB",
        "os_min_version": "4.0.304",
        "kernel_features": ["overlay_fs"]
    },
    "monitor": {
        "check_cmd": "ps |grep xxx|grep -v",
        "startup_cmd": "xxx",
        "auto_restart": true,
        "max_retries": 3
    },
    "integrity": {
        "algorithm": "sha256",
        "signature_algorithm": "rsa-3072-sha256",
        "signature_file": "manifest.json.sig",
        "files": [{"path": "scripts/start.sh", "sha256": "..."}]
    }
}
```

### 14.3 统一安装/卸载接口

保留Shell入口（兼容现有前端），但内部调用统一逻辑：

```bash
# 安装（在线）
appmarket.sh install appid={appid} enabled={yes|no}

# 安装（离线）
appmarket.sh install_file filename={file} mode={0|1|2}

# 卸载
appmarket.sh uninstall appid={appid} backup={0|1}

# 更新
appmarket.sh update_app appid={appid}

# 启用/禁用
appmarket.sh up appid={appid}
appmarket.sh down appid={appid}

# 配置
appmarket.sh update_config appid={appid} config={base64_json}
```

### 14.4 统一进程监控接口

将PMD的monitor.c能力暴露为Shell可调用的接口：

```bash
# 添加监控
appmarket.sh monitor_add name={name} check_cmd={cmd} startup_cmd={cmd}

# 移除监控
appmarket.sh monitor_remove name={name}

# 查询状态
appmarket.sh monitor_status name={name}
```

**实现方式**：
- 短期: PMD daemon通过Socket/Unix Socket接收Shell命令
- 长期: 统一C daemon，同时管理AppMarket和PMD的安装/监控

### 14.5 OSPF组件化建议

将OSPF从固件固化的Shell脚本改造为ipkg包：

```
manifest.json
manifest.json.sig
scripts/
  PRE_INST.sh     — 创建/etc/fq/frr目录
  start.sh        — 启动watchfrr
  stop.sh         — 停止watchfrr
  POST_INST.sh    — 迁移SQLite配置
app/bin/
  zebra           — FRR二进制
  ospfd
  ospf6d
  staticd
  watchfrr
  vtysh
  frr-reload      — C实现的热重载工具
monitor.json        — 监控配置
```

**优势**：
- OSPF版本可独立更新（不需刷固件）
- 统一签名验证
- 统一进程监控
- 空间节省（不需要OSPF的设备不安装）

### 14.6 统一服务端协议建议

方向：HTTP REST + WebSocket/SSE推送

```
设备 → 服务端:
  POST /api/v1/device/login     — 登录（替代PMD TCP协议）
  GET  /api/v1/device/tasks     — 拉取任务（轮询或SSE）
  POST /api/v1/device/report    — 上报结果

服务端 → 设备（通过SSE）:
  event: install   {name, version, download_url, ...}
  event: uninstall {name}
  event: config    {name, config}

前端 → 服务端:
  GET  /api/v1/apps              — 应用列表
  POST /api/v1/apps/{id}/install — 触发安装
  GET  /api/v1/devices/{gwid}/status — 设备状态
```

### 14.7 迁移路径建议

```mermaid
flowchart LR
    P1["阶段1: 统一数据层"] --> P2["阶段2: 统一包格式"]
    P2 --> P3["阶段3: 统一进程监控"]
    P3 --> P4["阶段4: 统一服务端"]
    P4 --> P5["阶段5: OSPF等OS功能组件化"]
```

| 阶段 | 目标 | 具体内容 |
|------|------|----------|
| 阶段1 | 统一数据层 | AppMarket SQLite吸收PMD的包记录；PMD的AES JSON DB作为过渡，最终废弃；前端保持不变 |
| 阶段2 | 统一包格式 | .bin.pkg → ipkg（tar.gz + RSA签名）；PMD包增加manifest.json + 签名；设备端统一用`__native_app_verify_integrity`验证 |
| 阶段3 | 统一进程监控 | PMD monitor.c能力扩展到监控所有应用；AppMarket的run.status废弃；Shell通过Unix Socket调用PMD监控 |
| 阶段4 | 统一服务端 | plugin.ikuai8.com + pkgmanager.ikuai8.com 合并；HTTP REST + SSE 替代 TCP自有协议；前端直接对接统一API |
| 阶段5 | OS功能组件化 | OSPF → ipkg包；其他OS功能（VRRP/BFD等）逐步迁移；固件只包含最小化系统 |

---

## 附录：关键安全机制汇总

### AppMarket签名验证

- 算法: RSA-3072 + SHA-256
- 公钥: `/etc/ssl/default/appmarket_plugin_sign_public.pem`
- 验证: `openssl dgst -sha256 -verify`
- 文件范围: `scripts/*`, `app/bin/*`
- 路径安全: 拒绝绝对路径/目录遍历

### PMD加密

- 通信: AES-256-CBC（key/iv硬编码在函数中）
- 数据库: AES-256-CBC（另一组key/iv）
- 包文件: AES-256-CBC（key在JSON下发）
- 无签名验证（仅MD5完整性校验）

### DevSpace授权

- 算法: RSA-3072 PKCS#1 v1.5 + SHA-256
- 签名域: `"DEVSPACE:DSL:V2\0" || payload`
- 签发者指纹水印（hostname/user/machine-id）
- 有效期控制

### OSPF

- 无加密无签名（固件内置）
- iptables规则控制OSPF协议包
