业务接口版本为 5,配置结构修订版为 13。配置只通过内联的 configYaml 或 configYamls 传入;每份已加载的 VCore 运行时最多拥有一个公共实例。代理组实时选择沿用 Controller,不增加 Invoke method 或版本协商。
char *VCoreInvoke(const char *request_json);
#ifdef _WIN32
char *VCoreWindowsVpnInvoke(const char *request_json);
#endif
void VCoreFree(char *response);- 请求必须是以 NUL 结尾的 UTF-8 JSON。
- 非空响应由 VCore 分配,调用方必须使用同一库中的
VCoreFree释放。 - 非法输入、未知方法、状态错误和 panic 返回合法失败 JSON;只有灾难性分配失败可以返回
NULL。 - 业务运行时线程不能重入 Invoke;Debug 和 Release 构建都立即返回失败 JSON,包括
version等只读请求。 - 请求正文、响应正文、完整配置、UUID、密钥、short ID 和凭据不得写入日志。
VCoreWindowsVpnInvoke是 Windows 安装包桥接接口,不属于业务 API v5。VCoreWindowsVpnInvoke当前在调用线程上初始化 MTA;调用线程必须尚未初始化 COM,或已经是 MTA。STA/ASTA 调用不受支持。
请求:
{
"apiVersion": 5,
"method": "getState",
"instanceId": "1",
"payload": {}
}成功响应:
{"success":true,"data":{},"error":""}失败响应:
{"success":false,"data":null,"error":"invalid configuration"}约束:
apiVersion必填且只能为5。method必须来自本文列出的白名单。payload必须是对象;无参数时传{}。- 运行时级方法必须省略
instanceId;实例级方法必须携带 VCore 返回的非空 ID。 - 未知 envelope 字段和未知 payload 字段都会失败。
- 无业务数据的方法成功时返回空对象,不返回
null。 - Invoke envelope 最大 3 MiB,单份 YAML 最大 256 KiB。
每份已加载的 VCore 运行时先调用:
{
"apiVersion": 5,
"method": "initialize",
"payload": {"dataDir": "/absolute/path"}
}dataDir 必须是可写绝对路径。VCore 固定使用:
<dataDir>/configs # 宿主可选持久化目录,不是 Invoke 输入
<dataDir>/geodata # VCore 管理的 GeoData 目录
同一路径重复初始化幂等,切换路径失败。
公共实例状态:
stopped -> preparing -> prepared -> starting -> running
^ |
+------------- stopping <-------------+
关键数据面提前退出 -> failed
instanceId是当前运行时内不可复用的代次令牌,不代表支持并行公共实例。- 同一实例一次只执行一个生命周期命令,重叠命令立即失败。
validateConfig是可并发的纯校验方法。measureDelay使用独立批次和私有工作器,不进入公共实例表。- 不支持配置热重载;切换配置需要
stop -> prepare -> start。唯一的运行期路由变更是通过 Controller 修改静态select组的当前选择,它不修改已 prepare 的配置。 stop在 stopped 状态幂等;destroyInstance是最终同步清理屏障。
运行时级方法:
{"apiVersion":5,"method":"version","payload":{}}返回:
{
"apiVersion": 5,
"buildIdentity": "VCore;engine=rust;coreVersion=0.1.0;invokeApiVersion=5;configVersion=13",
"configVersion": 13,
"engine": "rust",
"version": "0.1.0"
}configVersion 是二进制报告的结构修订号,不是 YAML 字段。源码 revision 和产物 hash 由发布系统记录。
参数和幂等语义见“初始化与生命周期”。成功时返回规范化后的 dataDir。
运行时级只读方法,要求已经初始化:
{"apiVersion":5,"method":"getGeoDataState","payload":{}}返回 geosite 和 geoip 两项:
{
"geosite": {
"required": true,
"available": false,
"updating": false,
"lastSuccess": null,
"nextCheck": null,
"lastError": null,
"etag": null,
"hash": null
},
"geoip": {
"required": false,
"available": false,
"updating": false,
"lastSuccess": null,
"nextCheck": null,
"lastError": null,
"etag": null,
"hash": null
}
}时间使用 Unix 秒,hash 为小写 SHA-256。调用不会创建实例、联网或改变更新调度。
{"apiVersion":5,"method":"createInstance","payload":{}}返回:
{"instanceId":"1"}该方法只创建 stopped 状态记录。实例销毁前再次创建失败。
实例级方法:
{"apiVersion":5,"method":"destroyInstance","instanceId":"1","payload":{}}实例仍处于 prepared、running 或 failed 时,先执行与 stop 等价的清理。取得命令锁后,无论清理成功、失败或 panic,ID 都会永久失效;只有因 busy 在取得命令锁前被拒绝时,实例才保留。
运行时级方法:
{
"apiVersion": 5,
"method": "validateConfig",
"payload": {"configYaml": "proxies:\n - name: edge\n ...\n"}
}完成大小、YAML、结构、共享 route-target 命名空间、引用、具体节点 dialer-proxy 图、代理组 DAG 和字段组合校验。不创建实例、不解析远端域名、不联网,也不读取 GeoData。资产缺失不影响纯配置校验。
实例级方法,只允许 stopped 状态:
{
"apiVersion": 5,
"method": "prepare",
"instanceId": "1",
"payload": {"configYaml": "proxies:\n - name: edge\n ...\n"}
}- 读取当时可用的本地 GeoData,不启动或等待下载。
- 只为直接访问物理网络的代理根节点执行引导 DNS;代理链上的域名交给下一跳。
- 校验每个静态
select组的初始选择;省略default-selected时使用第一项,显式值必须是直接成员。可变的 session 选择状态到start时才创建。 - 成功进入 prepared;失败释放临时资源并回到 stopped。
- 含 TUN 的配置从 preparing 起持有运行时本地的 TUN/protect 租约,直到停止或销毁。
- Android 只有在实际启用 TUN 时才要求事先注册 protect controller。
Apple 和 Android 的 TUN 启动参数:
{
"apiVersion": 5,
"method": "start",
"instanceId": "1",
"payload": {"tunFd":23,"tunFraming":"utun"}
}Android 使用 rawIp。非 TUN 配置必须省略 tunFd 和 tunFraming。
tunFd由宿主借用,宿主必须预先设置 nonblocking。- VCore 校验后建立带
CLOEXEC的副本,只关闭副本。 - Apple 只接受
utun,Android 只接受rawIp。 - 从 prepared 配置创建本次 session 的代理组选择状态。
- 所有监听器和关键数据面成功后才进入 running。
- GeoData 更新只在启动后按需后台运行,不属于启动关键路径。
- Windows 系统 VPN 使用安装包桥接接口,不使用文件描述符启动参数。
{"apiVersion":5,"method":"stop","instanceId":"1","payload":{}}同步取消并等待监听器、Controller、TUN、netstack、DNS、会话、出站和更新任务,关闭 VCore 持有的文件描述符副本并释放平台回调租约。返回后不得继续产生数据包或调用 protect callback;本次 session 的代理组选择随之销毁。
{"apiVersion":5,"method":"getState","instanceId":"1","payload":{}}返回:
{"state":"running","lastError":""}异步数据面失败时状态为 failed,lastError 只包含有界且脱敏的摘要。
运行时级方法:
{
"apiVersion": 5,
"method": "measureDelay",
"payload": {
"configYamls": ["proxies:\n - name: edge\n ...\n"],
"timeout": 5,
"url": "https://cp.cloudflare.com/"
}
}返回顺序与输入一致:
{
"results": [
{"success":true,"delay":123,"error":""},
{"success":false,"error":"measureDelay probe failed"}
]
}configYamls接受 1–5 份非空节点配置,timeout为 1–30 秒。- 同一运行时一次只允许一个测速批次,最多并发五个私有工作器。
- 节点配置顶层只允许
proxies,不接受proxy-groups;dialer-proxy也只能引用具体节点。VCore 推导唯一链头,且该链必须覆盖全部节点。 - 工作器只准备出站图并执行 TCP、可选 TLS 和 HTTP/1.1 HEAD;不创建公共实例、监听器、TUN、DNS、规则、嗅探器或 GeoData。
- URL 必须是无 userinfo 和 fragment 的绝对 HTTP/HTTPS URL;HTTPS 使用发布信任根。
- 任意合法 HTTP 状态都表示探测成功;不跟随重定向、不读取正文。
- 单项失败不取消其他项;方法返回前释放全部私有任务。
Android TUN 通过 Invoke 之外的运行时本地回调注册:
ProtectFd(fd) -> bool
- 含 TUN 的实例必须在
prepare前注册;非 TUN 和measureDelay不需要。 - 每个出站 TCP/UDP socket 在 connect 前同步调用 protect。
- 返回 false、抛出异常或 controller 失效都会使当前连接失败关闭。
- 回调必须快速、同步、非阻塞,且不能重入 Invoke 或注册接口。
- TUN 租约存活期间不能替换或注销 controller;
stop/destroyInstance是释放屏障。 - Android binding 使用 UTF-8
byte[],不依赖 Modified UTF-8。
配置 external-controller 后,运行时可提供回环 GET /traffic、GET /group、GET /group/{name}、GET /proxies/{name} 和 PUT /proxies/{name}。代理组 Controller 可以在非 TUN 的本地 HTTP 配置中运行;此时 /traffic 不存在。只要 Controller 管理代理组,secret 就必填并保护全部路由。
组成员列表是配置期固定的,选择只存于当前 Running Session。成功切换只影响之后新建的物理 TCP、UDP 和 DNS transport,不迁移既有连接、UDP association、DNS 状态或 TCP pool,也不触发 failover。Controller 查询不携带 instanceId,不进入 Invoke 命令锁;完整语义见 Controller API。
VCoreWindowsVpnInvoke 使用独立的桥接修订版 3:
{"bridgeVersion":3,"method":"getVpnStatus","payload":{}}只接受六个方法:
getEnvironmentgetVpnStatusstartVpnstopVpngetStartupTaskStatussetStartupTaskEnabled
startVpn 的 payload 为:
{
"configYaml": "tun:\n enable: true\n...",
"networkSettings": {
"ipv4Address": "192.168.3.1",
"ipv6Address": "fd00::2",
"dnsIpv4Address": "8.8.8.8",
"dnsIpv6Address": "2001:4860:4860::8888"
},
"policy": {
"alwaysOn": false,
"allowLocalNetwork": true,
"excludedCidrs": []
},
"sessionBackend": {
"processes": [
{
"executableRelativePath": "bin\\proxy-core.exe",
"arguments": ["run", "--mode", "vpn"]
}
]
}
}policy 始终必填。Windows VPN 固定覆盖所有应用;alwaysOn 控制 profile capability,实际自动连接仍取决于 Windows 用户设置和 active profile;allowLocalNetwork 控制本地子网是否绕过;excludedCidrs 是最多 64 个规范 IPv4/IPv6 目标网段。拒绝重复项、host bits、/0、禁用 IPv6 时的 IPv6 项,以及包含当前 VPN DNS 地址的项。
sessionBackend 可以省略。存在时包含 1..=8 个有序关键进程;每项只有 package installed location 内的规范 .exe 相对路径和有界 argv 数组。同一可执行文件可出现多次。第一版不接受 port、UDP、readiness、restart、environment、working directory 或 raw command line;任一进程退出都会使当前 VPN 会话失败关闭。
桥接把 YAML、进程顺序、路径和参数发布为 vcore-session-v2:<sha256> Session Snapshot。参数引用的文件由调用方保持存在且不可变,VCore 不读取或摘要其内容。getVpnStatus.data.snapshotToken 返回该完整 Session token。
桥接请求最大 1 MiB。它负责安装包身份、单一 VPN profile、不可变 Session Snapshot、连接/断开命令和系统 VPN 状态;Provider 负责激活 Session Host。桥接不公开 profile CRUD、内部文件路径、backend 描述、参数、PID、管道名称或 Snapshot 维护。数据包、Controller 流量查询、代理组查询/切换和业务生命周期不经过该 JSON 桥接。
- 所有 JSON DTO 拒绝未知字段。
- 配置、错误和日志按 UTF-8 字节计数并受固定上限约束。
- TUN 原始数据包解析最大 1,500 字节;最终代理 UDP 响应按有效 MTU 减去 48 字节限制,其他 TUN 平台最大 1,452 字节,Windows 最大 1,352 字节。
- 嵌套 UDP 协议可以增加有界帧头,但解封装后的最终负载仍受该平台响应上限限制。
- 节点和代理组定义名共享大小写敏感的严格 UTF-8 命名空间;
DIRECT、REJECT和RULES不能用作定义名。 - Secret、password、UUID、REALITY key、short ID、目标地址和完整配置不得进入日志。