mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 14:50:45 +00:00
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:
@@ -0,0 +1,220 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""验证「配对码被占用」的处理。
|
||||
|
||||
用户的要求:
|
||||
一个设备设了 789113,另一台也想设 789113 -> 不行,
|
||||
要弹通知说「该配对码已被使用,请换一个配对码」。
|
||||
|
||||
分两层验证:
|
||||
1. 中转服务器层:第二台设备报同一个码 -> 必须被拒,且带 codeTaken
|
||||
2. 被控端层:RelayLink 必须抛 RelayCodeTaken,并且**调用 on_alert 弹通知**
|
||||
而且不能反复重试刷屏(换了码才继续)
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
_UA = {"User-Agent": "LanRemote/1.4.0"}
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
sys.path.insert(0, str(ROOT / "windows"))
|
||||
|
||||
RELAY_PORT = 8093
|
||||
RELAY_URL = f"http://127.0.0.1:{RELAY_PORT}"
|
||||
CODE = "789113"
|
||||
OTHER_CODE = "654321"
|
||||
|
||||
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 post(path, payload):
|
||||
body = json.dumps(payload, ensure_ascii=False).encode("utf-8")
|
||||
req = urllib.request.Request(RELAY_URL + path, data=body,
|
||||
method="POST", headers=_UA)
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=15) as resp:
|
||||
return resp.status, json.loads(resp.read().decode("utf-8"))
|
||||
except urllib.error.HTTPError as exc:
|
||||
return exc.code, json.loads(exc.read().decode("utf-8", "replace"))
|
||||
|
||||
|
||||
def main() -> int:
|
||||
work = Path(tempfile.mkdtemp(prefix="code_conflict_"))
|
||||
relay = None
|
||||
try:
|
||||
# ---------- 起本地中转 ----------
|
||||
relay_data = work / "relaydata"
|
||||
relay_data.mkdir(parents=True, exist_ok=True)
|
||||
env = dict(os.environ)
|
||||
env.update({
|
||||
"RELAY_PORT": str(RELAY_PORT), "RELAY_BIND": "127.0.0.1",
|
||||
"RELAY_DATA": str(relay_data), "RELAY_POLL": "6",
|
||||
"PYTHONIOENCODING": "utf-8", "PYTHONUNBUFFERED": "1",
|
||||
})
|
||||
relay = subprocess.Popen(
|
||||
[sys.executable, "-u", str(ROOT / "relay" / "relay.py")], env=env,
|
||||
stdout=open(work / "relay.log", "wb"),
|
||||
stderr=subprocess.STDOUT)
|
||||
up = False
|
||||
for _ in range(40):
|
||||
time.sleep(0.5)
|
||||
try:
|
||||
with urllib.request.urlopen(
|
||||
urllib.request.Request(RELAY_URL + "/v1/health",
|
||||
headers=_UA),
|
||||
timeout=2) as resp:
|
||||
if resp.status == 200:
|
||||
up = True
|
||||
break
|
||||
except Exception: # noqa: BLE001
|
||||
continue
|
||||
check("本地中转起来了", up)
|
||||
if not up:
|
||||
print((work / "relay.log").read_text(encoding="utf-8",
|
||||
errors="replace")[-600:])
|
||||
return 1
|
||||
|
||||
print()
|
||||
print("一、中转服务器层")
|
||||
status, first = post("/v1/agent/register", {
|
||||
"deviceId": "pc-A", "code": CODE, "name": "电脑A",
|
||||
"version": "1.4.0"})
|
||||
check("第一台设备登记成功", first.get("ok") is True, first)
|
||||
check("第一台拿到了令牌", bool(first.get("token")))
|
||||
check("第一台的码就是它设的", first.get("code") == CODE,
|
||||
first.get("code"))
|
||||
|
||||
status, second = post("/v1/agent/register", {
|
||||
"deviceId": "pc-B", "code": CODE, "name": "电脑B",
|
||||
"version": "1.4.0"})
|
||||
check("第二台用同一个码被拒", second.get("ok") is False, second)
|
||||
check("返回了 codeTaken 标记", second.get("codeTaken") is True, second)
|
||||
check("错误说明了要换码",
|
||||
"已被使用" in str(second.get("error"))
|
||||
and "换一个" in str(second.get("error")),
|
||||
second.get("error"))
|
||||
check("第二台没拿到令牌", not second.get("token"), second)
|
||||
|
||||
status, third = post("/v1/agent/register", {
|
||||
"deviceId": "pc-B", "code": OTHER_CODE, "name": "电脑B",
|
||||
"version": "1.4.0"})
|
||||
check("第二台换个码就能登记", third.get("ok") is True, third)
|
||||
check("它拿到的是新码", third.get("code") == OTHER_CODE,
|
||||
third.get("code"))
|
||||
|
||||
# 单设备单码仍然有效:A 报新码应被改回
|
||||
status, again = post("/v1/agent/register", {
|
||||
"deviceId": "pc-A", "code": "111222", "name": "电脑A",
|
||||
"version": "1.4.0"})
|
||||
check("A 报新码被改回原来的(单设备单码)",
|
||||
again.get("code") == CODE, again.get("code"))
|
||||
|
||||
print()
|
||||
print("二、被控端层(RelayLink 要弹通知)")
|
||||
from lanremote.config import Store
|
||||
from lanremote.relay import RelayCodeTaken, RelayLink
|
||||
|
||||
alerts = []
|
||||
|
||||
def on_alert(title, text):
|
||||
alerts.append((title, text))
|
||||
|
||||
# A 的 store
|
||||
store_a = Store(work / "store_a")
|
||||
store_a.set_pairing_code(CODE)
|
||||
store_a.set("server_name", "电脑A")
|
||||
store_a.set("relay_device_id", "pc-A")
|
||||
link_a = RelayLink(store_a, log=lambda _m: None, on_alert=on_alert)
|
||||
link_a.start(RELAY_URL)
|
||||
time.sleep(4)
|
||||
check("A 连上并登记", link_a.status().get("online") is True
|
||||
or link_a.token != "", link_a.status())
|
||||
check("A 没有冲突", not link_a.status().get("codeConflict"),
|
||||
link_a.status().get("codeConflict"))
|
||||
|
||||
# B 故意用同一个码
|
||||
store_b = Store(work / "store_b")
|
||||
store_b.set_pairing_code(CODE)
|
||||
store_b.set("server_name", "电脑B")
|
||||
store_b.set("relay_device_id", "pc-B")
|
||||
alerts.clear()
|
||||
link_b = RelayLink(store_b, log=lambda _m: None, on_alert=on_alert)
|
||||
link_b.start(RELAY_URL)
|
||||
time.sleep(6)
|
||||
|
||||
check("B 弹了通知", len(alerts) >= 1, f"{len(alerts)} 次: {alerts[:2]}")
|
||||
if alerts:
|
||||
title, text = alerts[0]
|
||||
check("通知标题说了配对码", "配对码" in title, title)
|
||||
check("通知正文说要换码",
|
||||
"已被使用" in text and "换" in text, text)
|
||||
check("B 停在冲突状态(没有反复重试刷屏)",
|
||||
bool(link_b.status().get("codeConflict")),
|
||||
link_b.status().get("codeConflict"))
|
||||
check("B 的冲突信息里带着要换码的提示",
|
||||
"已被使用" in str(link_b.status().get("codeConflict")),
|
||||
link_b.status().get("codeConflict"))
|
||||
|
||||
count_before = len(alerts)
|
||||
time.sleep(6)
|
||||
check("同一个码不会反复弹通知",
|
||||
len(alerts) == count_before,
|
||||
f"又弹了 {len(alerts) - count_before} 次")
|
||||
|
||||
print()
|
||||
print("三、用户换码之后要能自己恢复")
|
||||
store_b.set_pairing_code(OTHER_CODE)
|
||||
time.sleep(8)
|
||||
check("换了码之后 B 连上了",
|
||||
link_b.status().get("online") is True or link_b.token != "",
|
||||
link_b.status())
|
||||
check("冲突标记被清掉",
|
||||
not link_b.status().get("codeConflict"),
|
||||
link_b.status().get("codeConflict"))
|
||||
|
||||
for link in (link_a, link_b):
|
||||
try:
|
||||
link.stop()
|
||||
except Exception: # noqa: BLE001
|
||||
pass
|
||||
|
||||
print()
|
||||
print("=" * 62)
|
||||
print(f"通过 {passed} 项,失败 {failed} 项")
|
||||
return 0 if failed == 0 else 1
|
||||
finally:
|
||||
if relay is not None:
|
||||
try:
|
||||
relay.terminate()
|
||||
relay.wait(timeout=8)
|
||||
except Exception: # noqa: BLE001
|
||||
try:
|
||||
relay.kill()
|
||||
except Exception: # noqa: BLE001
|
||||
pass
|
||||
time.sleep(0.5)
|
||||
shutil.rmtree(work, ignore_errors=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user