Files
ykxmz/_build/patch_code_conflict.py
xmz7891 b62ac865ea 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 + 双连接

文档
- 许可协议 / 安装前必读 / 安装后须知(作者:小麦子)
2026-10-06 19:01:05 +08:00

232 lines
9.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""配对码被占用时,在电脑上弹通知。
用户的要求:
"如果一个设备设置了配对码 789113,另一个设备也想设置 789113,
那不可以,你就弹通知,说该配对码已被使用,请换一个配对码"
现状:
中转服务器**已经**会拒绝(返回 "这个配对码已经被另一台设备用了,换一个"),
被控端也抛了这个错误 —— 但只是写进日志,用户根本看不到。
而且主循环会当成网络错误一直重试,刷屏。
要做的:
1. 中转返回里加 codeTaken 标记(让客户端能精确识别,不靠匹配中文)
2. 被控端加 RelayCodeTaken 异常
3. 加 on_alert 回调 —— 服务器把它接到界面通知上
4. 主循环遇到冲突时:**弹一次通知就停下来等**,不要反复重试刷屏
用户换了配对码之后自动继续。
"""
from __future__ import annotations
import sys
from pathlib import Path
ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote")
RELAY_SERVER = ROOT / "relay" / "relay.py"
RELAY_CLIENT = ROOT / "windows" / "lanremote" / "relay.py"
SERVER = ROOT / "windows" / "lanremote" / "server.py"
# ============ 1. 中转:返回加 codeTaken ============
SRV_OLD = ''' known = self.codes.get(code)
if known and known != device_id:
return {"ok": False,
"error": "这个配对码已经被另一台设备用了,换一个"}'''
SRV_NEW = ''' known = self.codes.get(code)
if known and known != device_id:
# codeTaken 让客户端能精确识别这种冲突,
# 不用去匹配中文错误文案(文案一改就坏)。
self.log(f"配对码 {code} 已被 {known} 占用,拒绝 {device_id}")
return {"ok": False,
"codeTaken": True,
"error": "该配对码已被使用,请换一个配对码"}'''
# ============ 2. 被控端:异常类 ============
EXC_ANCHOR = '''class _AuthLost(Exception):'''
EXC_NEW = '''class RelayCodeTaken(RelayError):
"""配对码被别的设备占了。
这**不是网络问题**,重试没用 —— 要等用户换一个配对码。
所以主循环遇到它不能当成普通错误一直重试(会刷屏),
而是弹一次通知然后停下等。
"""
class _AuthLost(Exception):'''
# ============ 3. 被控端:__init__ 加 on_alert ============
INIT_OLD = ''' def __init__(self, store, log=None, on_session=None) -> None:
self.store = store
self._log = log or (lambda _m: None)
self._on_session = on_session'''
INIT_NEW = ''' def __init__(self, store, log=None, on_session=None, on_alert=None) -> None:
self.store = store
self._log = log or (lambda _m: None)
self._on_session = on_session
# 出需要用户处理的事(比如配对码被占)时调这个,用来弹通知
self._on_alert = on_alert'''
INIT2_OLD = ''' self.sessions_served = 0'''
INIT2_NEW = ''' self.sessions_served = 0
# 配对码冲突的说明。非空表示现在卡在这,等用户换码。
self.code_conflict = ""
self._alerted_code = ""'''
# ============ 4. 被控端:_register 抛专用异常 ============
REG_OLD = ''' if not reply.get("ok"):
raise RelayError(str(reply.get("error") or "登记被拒"))'''
REG_NEW = ''' if not reply.get("ok"):
message = str(reply.get("error") or "登记被拒")
# 配对码被占:精确判断(服务端会带 codeTaken),
# 兼容老服务端就匹配关键字。
if reply.get("codeTaken") or "已被" in message and "配对码" in message:
raise RelayCodeTaken(message)
raise RelayError(message)
# 登记成功 -> 之前的冲突解除了
self.code_conflict = ""'''
# ============ 5. 被控端:主循环处理冲突 ============
RUN_OLD = ''' except _AuthLost:
self._log("中转说令牌失效,重新登记")
self.token = ""
time.sleep(1)'''
RUN_NEW = ''' except _AuthLost:
self._log("中转说令牌失效,重新登记")
self.token = ""
time.sleep(1)
except RelayCodeTaken as exc:
# 配对码被别的设备占了。这不是网络问题,重试没用。
# 弹一次通知,然后**停下来等用户换码**。
message = str(exc) or "该配对码已被使用,请换一个配对码"
self.online = False
self.token = ""
self.last_error = message
self.code_conflict = message
current = self.store.pairing_code()
if current != self._alerted_code:
# 只在换了新码之后再弹,避免反复弹同一个码的通知
self._alerted_code = current
self._log(f"配对码冲突:{message}")
if self._on_alert:
try:
self._on_alert("配对码被占用", message)
except Exception: # noqa: BLE001
pass
# 等用户换码。每 5 秒看一次配对码变没变。
for _ in range(12):
if not self._running:
return
time.sleep(0.5)
if self.store.pairing_code() != current:
self._log("配对码变了,重新登记")
self._alerted_code = ""
break
continue'''
# ============ 6. 被控端:status 里带上冲突信息 ============
STATUS_OLD = ''' "candidates": list(self.candidates),'''
STATUS_NEW = ''' "candidates": list(self.candidates),
"codeConflict": self.code_conflict,'''
# ============ 7. 服务器:把 on_alert 接到界面通知 ============
WIRE_OLD = ''' self._relay = RelayLink(self.store, log=self._log,
on_session=self.adopt_relay_socket)'''
WIRE_NEW = ''' self._relay = RelayLink(self.store, log=self._log,
on_session=self.adopt_relay_socket,
on_alert=self._alert)'''
def patch(path: Path, pairs, label: str) -> bool:
text = path.read_text(encoding="utf-8")
ok = True
for old, new, tag in pairs:
if old not in text:
print(f" [{label}] [跳过] {tag} —— 锚点没找到")
ok = False
continue
text = text.replace(old, new, 1)
print(f" [{label}] {tag}")
path.write_text(text, encoding="utf-8", newline="\n")
return ok
def main() -> int:
ok = True
ok &= patch(RELAY_SERVER, [(SRV_OLD, SRV_NEW, "冲突返回加 codeTaken")],
"中转")
ok &= patch(RELAY_CLIENT, [
(EXC_ANCHOR, EXC_NEW, "RelayCodeTaken 异常"),
(INIT_OLD, INIT_NEW, "__init__ 加 on_alert"),
(INIT2_OLD, INIT2_NEW, "__init__ 加冲突字段"),
(REG_OLD, REG_NEW, "_register 抛专用异常"),
(RUN_OLD, RUN_NEW, "主循环处理冲突"),
(STATUS_OLD, STATUS_NEW, "status 带冲突信息"),
], "被控端")
# 服务器:加 _alert 方法 + 接线
text = SERVER.read_text(encoding="utf-8")
if WIRE_OLD in text:
text = text.replace(WIRE_OLD, WIRE_NEW, 1)
print(" [服务器] on_alert 接线")
else:
print(" [服务器] [跳过] 接线锚点没找到")
ok = False
alert_method = ''' def _alert(self, title: str, text: str) -> None:
"""给用户看的通知(配对码被占这类必须让人知道的事)。
走界面的通知,用户在电脑上能直接看到。
界面还没起来时退回写日志,至少不丢信息。
"""
self._log(f"[需要处理] {title}:{text}")
try:
ui = getattr(self.actions, "ui", None)
if ui is not None and hasattr(ui, "notify"):
ui.notify(title, text)
except Exception: # noqa: BLE001
pass
def relay_status(self) -> dict:'''
if "def _alert(" in text:
print(" [服务器] 已经有 _alert")
elif " def relay_status(self) -> dict:" in text:
text = text.replace(" def relay_status(self) -> dict:",
alert_method, 1)
print(" [服务器] 加了 _alert 方法")
else:
print(" [服务器] [失败] 找不到 relay_status")
ok = False
SERVER.write_text(text, encoding="utf-8", newline="\n")
import ast
for label, path in (("中转", RELAY_SERVER), ("被控端", RELAY_CLIENT),
("服务器", SERVER)):
try:
ast.parse(path.read_text(encoding="utf-8"))
print(f" {label} 语法 OK")
except SyntaxError as exc:
print(f" {label} 语法错误: {exc}")
ok = False
return 0 if ok else 1
if __name__ == "__main__":
sys.exit(main())