mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 16:00:43 +00:00
被控端 - 修复 MTU 问题:夹 MSS + 路径 MTU 探测(公网可用率 48% -> 100%) - 复用 HTTP 连接(免掉每次新建 TLS 的 30% 握手失败) - 每分钟回头找局域网,自动切回快 400 倍的路径 - 画面心跳帧:静止时省流量,客户端仍知道流是活的 - 锁屏时给出可操作的提示 手表端 - 内置 GTS Root R4 / GlobalSign Root CA,修 SSLHandshakeException - 连接错误翻译成人话(证书/时间/解析/超时分别提示) - 经中转连上后用服务器报的地址刷新已配对记录 - 新增局域网连接页面、服务器延迟检测 服务器端 - 支持 chunked 请求体(修每 16 秒一次的连接错乱与大面积 502) - 网络调优脚本 net-tune.sh(开机自动应用) - 管理页:批量删除、网络体检、下载区 - 隧道改 HTTP/2 + 双连接 文档 - 许可协议 / 安装前必读 / 安装后须知(作者:小麦子)
232 lines
9.2 KiB
Python
232 lines
9.2 KiB
Python
# -*- 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())
|