ykxmz 1.5.0:修复手表端 TLS 证书校验 + MTU 修复网络稳定性

被控端
- 修复 MTU 问题:夹 MSS + 路径 MTU 探测(公网可用率 48% -> 100%)
- 复用 HTTP 连接(免掉每次新建 TLS 的 30% 握手失败)
- 每分钟回头找局域网,自动切回快 400 倍的路径
- 画面心跳帧:静止时省流量,客户端仍知道流是活的
- 锁屏时给出可操作的提示

手表端
- 内置 GTS Root R4 / GlobalSign Root CA,修 SSLHandshakeException
- 连接错误翻译成人话(证书/时间/解析/超时分别提示)
- 经中转连上后用服务器报的地址刷新已配对记录
- 新增局域网连接页面、服务器延迟检测

服务器端
- 支持 chunked 请求体(修每 16 秒一次的连接错乱与大面积 502)
- 网络调优脚本 net-tune.sh(开机自动应用)
- 管理页:批量删除、网络体检、下载区
- 隧道改 HTTP/2 + 双连接

文档
- 许可协议 / 安装前必读 / 安装后须知(作者:小麦子)
This commit is contained in:
xmz7891
2026-10-06 19:01:05 +08:00
commit b62ac865ea
3195 changed files with 203292 additions and 0 deletions
+188
View File
@@ -0,0 +1,188 @@
# -*- coding: utf-8 -*-
"""只读回归测试:开关的方向性 + 能开就要能关。
**重要:这个测试不执行任何破坏性功能。**
之前的版本会真的跑每一个 toggle,包括「锁键盘鼠标」(要管理员才能解)
和「任务栏自动隐藏」(会杀 explorer)——在用户真机上那是闯祸。
现在改成:
* 系统状态只用只读方式核对(注册表 / 窗口枚举)
* 只真正执行明确安全的开关(循环播放、随机播放)
* 其余开关只核对实现里两个方向都在
* 关窗口那条链路真的执行(它本来就是把东西关掉,安全)
"""
import ctypes
import os
import sys
import tempfile
import time
import winreg
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT / "windows"))
from lanremote.actions import Actions # noqa: E402
from lanremote.config import Store # noqa: E402
from lanremote.features import Features # noqa: E402
from lanremote.headless import HeadlessUI # noqa: E402
FEATURES_PY = ROOT / "windows" / "lanremote" / "features.py"
MAIN_JAVA = (ROOT / "android" / "src" / "com" / "lanremote" / "watch"
/ "MainActivity.java")
QUOTE = chr(34)
ON_ARG = "params.get(" + QUOTE + "on" + QUOTE + ")"
passed = 0
failed = 0
def check(name, ok, detail=""):
global passed, failed
if ok:
passed += 1
print(" [PASS] " + name)
else:
failed += 1
print(" [FAIL] " + name + " " + str(detail))
def visible_windows(keyword):
user32 = ctypes.windll.user32
proc = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.c_void_p)
found = []
def callback(hwnd, _l):
pid = ctypes.c_ulong()
user32.GetWindowThreadProcessId(hwnd, ctypes.byref(pid))
if pid.value != os.getpid() or not user32.IsWindowVisible(hwnd):
return True
length = user32.GetWindowTextLengthW(hwnd)
buf = ctypes.create_unicode_buffer(length + 2)
user32.GetWindowTextW(hwnd, buf, length + 2)
if keyword in buf.value:
found.append(buf.value)
return True
user32.EnumWindows(proc(callback), 0)
return found
def main() -> int:
store = Store(Path(tempfile.mkdtemp()))
ui = HeadlessUI(store)
actions = Actions(ui, store)
features = Features(actions)
ui.root
# ---------------------------------------------------------------
print("一、功能表完整性")
defs = features.defs()
check("功能数量 > 200", len(defs) > 200, str(len(defs)) + " 个")
missing = [d["name"] for d in defs
if not hasattr(features, "_do_" + d["name"])]
check("没有缺实现的功能", not missing, str(missing)[:120])
groups = sorted({d["group"] for d in defs})
check("分组数 = 14", len(groups) == 14, str(groups))
# ---------------------------------------------------------------
print()
print("二、每个开关都实现了两个方向")
toggles = [d for d in defs if d.get("kind") == "toggle"]
check("有 toggle 类功能", len(toggles) >= 8, str(len(toggles)) + " 个")
source = FEATURES_PY.read_text(encoding="utf-8")
one_way = []
for item in toggles:
name = item["name"]
index = source.find("def _do_" + name + "(")
body = source[index:index + 1400] if index > 0 else source
if ON_ARG not in body and "_truthy(params" not in body:
one_way.append(name)
check("所有开关都用到了 on 参数", not one_way,
"只往一个方向的: " + str(one_way))
main_java = MAIN_JAVA.read_text(encoding="utf-8")
has_put = "feature.put(" + QUOTE + "on" + QUOTE in main_java
check("手表 toggle 后会翻转本地缓存", has_put,
"没找到 feature.put(on, ...)")
# ---------------------------------------------------------------
print()
print("三、安全开关真的往返一次")
for name in ("loop_play", "shuffle_play"):
try:
on = features.run(name, {"on": True})
off = features.run(name, {"on": False})
check(name + " 两个方向话术不同", str(on) != str(off),
"开=" + repr(on) + " 关=" + repr(off))
except Exception as exc: # noqa: BLE001
check(name + " 往返", False, str(exc)[:80])
# ---------------------------------------------------------------
print()
print("四、手表开的画面必须能关掉")
ui.notify("测试通知一", "内容")
ui.notify("测试通知二", "内容")
time.sleep(1.2)
before = visible_windows("通知")
check("通知确实弹出来了", len(before) >= 2, str(len(before)) + " 个")
result = features.run("close_visuals", {})
time.sleep(1.2)
after = visible_windows("通知")
check("close_visuals 关掉了通知", len(after) == 0,
"关前 " + str(len(before)) + ",关后 " + str(len(after))
+ "(" + str(result) + ")")
features.run("big_text", {"text": "测试大字XYZ"})
time.sleep(1.0)
check("全屏大字弹出来了", len(visible_windows("测试大字XYZ")) >= 1)
features.run("close_visuals", {})
time.sleep(1.0)
check("close_visuals 关掉了全屏大字",
len(visible_windows("测试大字XYZ")) == 0)
again = features.run("close_visuals", {})
check("没东西可关时也不报错", "没有" in str(again), str(again))
# ---------------------------------------------------------------
print()
print("五、系统状态用只读方式核对")
with winreg.OpenKey(winreg.HKEY_CURRENT_USER,
r"Software\Microsoft\Windows\CurrentVersion"
r"\Explorer\StuckRects3") as key:
raw, _kind = winreg.QueryValueEx(key, "Settings")
blob = bytes(raw)
check("Settings 能读到且够长", len(blob) > 8, str(len(blob)) + " 字节")
check("_taskbar_hidden() 与注册表一致",
features._taskbar_hidden() == bool(blob[8] & 1),
"函数=" + str(features._taskbar_hidden())
+ " 注册表=" + str(bool(blob[8] & 1)))
from lanremote import autostart
try:
with winreg.OpenKey(winreg.HKEY_CURRENT_USER,
r"Software\Microsoft\Windows\CurrentVersion\Run"
) as key:
winreg.QueryValueEx(key, "LanRemoteAgent")
registry_on = True
except FileNotFoundError:
registry_on = False
check("is_enabled() 与注册表一致",
autostart.is_enabled() == registry_on,
"函数=" + str(autostart.is_enabled())
+ " 注册表=" + str(registry_on))
ui.stop()
print()
print("=" * 66)
print("通过 " + str(passed) + " 项,失败 " + str(failed) + " 项")
if failed:
print("失败项:")
return 0 if failed == 0 else 1
if __name__ == "__main__":
sys.exit(main())