ykxmz 1.5.0:手表端 TLS 证书兼容 + 三端分开打包 + 下载区

手表端
- 内置 GTS Root R4 / GlobalSign Root CA
  修 SSLHandshakeException: Chain validation failed
- 连接错误翻译成人话:证书 / 时间 / 解析 / 超时分别给提示
- 经中转连上后用服务器报的地址刷新已配对记录
- 版本号 1.3.0 -> 1.5.0(AndroidManifest 之前漏改了)

服务器端
- 支持 chunked 请求体,修每 16 秒一次的连接错乱与大面积 502
- 网络调优 net-tune.sh(开机自动应用)
- 新增下载区,管理页加下载卡片
- 隧道改 HTTP/2 + 双连接

打包方式变更
- 从一个合并 zip 改成三个独立产物:
    ykxmz-agent-*.zip    被控端
    ykxmz-server-*.zip   服务器端
    ykxmz-watch-*.apk    控制端
This commit is contained in:
xmz7891
2026-10-06 23:08:05 +08:00
parent edac13dbe2
commit 8111fb6d97
20 changed files with 3770 additions and 2943 deletions
+39 -21
View File
@@ -22,7 +22,13 @@ import zipfile
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
ZIP = ROOT / "dist" / "ykxmz-1.5.0.zip"
# 三端分开出(用户要求):
# 被控端 -> 一个 zip
# 服务器端 -> 一个 zip
# 控制端 -> 直接给 APK(不打 zip)
AGENT_ZIP = ROOT / "dist" / "ykxmz-agent-1.5.0.zip"
SERVER_ZIP = ROOT / "dist" / "ykxmz-server-1.5.0.zip"
WATCH_APK = ROOT / "dist" / "ykxmz-watch-1.5.0.apk"
TOOLCHAIN = Path(r"C:\Users\shu\Desktop\deepseekagent\starklink\toolchain")
JAVAC = TOOLCHAIN / "jdk17" / "bin" / "javac.exe"
JAVA = TOOLCHAIN / "jdk17" / "bin" / "java.exe"
@@ -45,44 +51,55 @@ def check(name, ok, detail=""):
def main() -> int:
if not ZIP.is_file():
print(f" 找不到 {ZIP}")
return 1
# 1) 三个产物都要在
for label, path in (("被控端包", AGENT_ZIP), ("服务器端包", SERVER_ZIP),
("控制端 APK", WATCH_APK)):
if not path.is_file():
print(f" 找不到{label}: {path}")
return 1
work = Path(tempfile.mkdtemp(prefix="verify_pkg_"))
relay_proc = agent_proc = None
try:
# ---------------- 1. 解压 ----------------
print("一、解压")
with zipfile.ZipFile(ZIP) as archive:
# ---------------- 1. 解压两个 zip ----------------
print("一、解压(两个 zip)")
with zipfile.ZipFile(AGENT_ZIP) as archive:
archive.extractall(work)
top = work / ZIP.stem
check("顶层目录存在", top.is_dir(), top)
agent_dir = top / "1-agent"
relay_dir = top / "2-server"
watch_dir = top / "3-watch"
check("三个部分目录都在",
agent_dir.is_dir() and relay_dir.is_dir() and watch_dir.is_dir())
check("顶层说明在", (top / "README.txt").is_file())
with zipfile.ZipFile(SERVER_ZIP) as archive:
archive.extractall(work)
# 两个包各自带一层版本目录
agent_dir = work / AGENT_ZIP.stem
relay_dir = work / SERVER_ZIP.stem
check("被控端目录存在", agent_dir.is_dir(), agent_dir)
check("服务器端目录存在", relay_dir.is_dir(), relay_dir)
exe = agent_dir / "ykxmz.exe"
relay_py = relay_dir / "relay.py"
install_sh = relay_dir / "install.sh"
apk = next(watch_dir.glob("*.apk"), None)
apk = WATCH_APK
check("被控端 EXE 在", exe.is_file())
check("服务器端 relay.py 在", relay_py.is_file())
check("服务器端 install.sh 在", install_sh.is_file())
check("控制端 APK 在", apk is not None, apk)
check("服务器端带了网络调优脚本", (relay_dir / "net-tune.sh").is_file())
check("服务器端带了看门狗", (relay_dir / "watchdog.sh").is_file())
check("控制端 APK 在(直接在 dist 里)", apk.is_file(), apk)
# 说明文档要有 BOM(否则记事本会认成 GBK 乱码)
for label, path in (("顶层", top / "README.txt"),
("被控端", agent_dir / "README-agent.txt"),
for label, path in (("被控端", agent_dir / "README-agent.txt"),
("服务器端", relay_dir / "README-server.txt"),
("控制端", watch_dir / "README-watch.txt")):
("控制端(旁边那份)",
ROOT / "dist" / "ykxmz-watch-1.5.0-说明.txt")):
raw = path.read_bytes() if path.is_file() else b""
check(f"{label}说明有 UTF-8 BOM",
raw[:3] == b"\xef\xbb\xbf", raw[:3])
# 三份正式文档:两个包里都要有
for label, base in (("被控端包", agent_dir), ("服务器端包", relay_dir)):
for doc in ("LICENSE.txt", "BEFORE-INSTALL.txt",
"AFTER-INSTALL.txt"):
check(f"{label}带了 {doc}", (base / doc).is_file())
# 被控端目录里不该有 data / 说明残留
check("没有把 data 目录打进去",
not (agent_dir / "data").exists())
@@ -179,7 +196,8 @@ def main() -> int:
classes.mkdir(parents=True, exist_ok=True)
sources = [ROOT / "android" / "src" / "com" / "lanremote" / "watch" / n
for n in ("Json.java", "B64.java", "Transport.java",
"RelayTransport.java", "RemoteClient.java",
"RelayTransport.java", "TlsCompat.java",
"RemoteClient.java",
"DiscoveryCore.java")]
sources.append(ROOT / "_tests" / "java" / "JavaRelayTest.java")
comp = subprocess.run(