mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 13:40:45 +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 + 双连接 文档 - 许可协议 / 安装前必读 / 安装后须知(作者:小麦子)
195 lines
7.0 KiB
Python
195 lines
7.0 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""验证局域网直连这条路是通的,以及安卓端新加的东西在。
|
||
|
||
顺序很关键(踩过):
|
||
之前是先广播、再起测试实例。单独跑时本机真有个在跑的 agent,
|
||
广播能搜到,测试过;但在完整回归里,套件会先 Stop-Strays
|
||
把 agent 杀掉,广播就一台都搜不到 —— 于是失败。
|
||
|
||
改成:**先起测试实例(它自己会绑 UDP 8766 应答),再广播**。
|
||
这样不依赖环境里有没有别的 agent。
|
||
如果 8766 被别的 agent 占着(单独跑时就是这样),
|
||
退而验证"搜到的那台能直连"。
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import json
|
||
import re
|
||
import socket
|
||
import sys
|
||
import tempfile
|
||
import time
|
||
from pathlib import Path
|
||
|
||
ROOT = Path(__file__).resolve().parent.parent
|
||
sys.path.insert(0, str(ROOT / "windows"))
|
||
sys.path.insert(0, str(ROOT / "_tests"))
|
||
|
||
MAIN = (ROOT / "android" / "src" / "com" / "lanremote" / "watch"
|
||
/ "MainActivity.java")
|
||
|
||
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 java_method(src: str, signature: str) -> str:
|
||
"""按花括号配平取 Java 方法体。"""
|
||
index = src.find(signature)
|
||
if index < 0:
|
||
return ""
|
||
start = src.find("{", index)
|
||
if start < 0:
|
||
return ""
|
||
depth = 0
|
||
for pos in range(start, len(src)):
|
||
if src[pos] == "{":
|
||
depth += 1
|
||
elif src[pos] == "}":
|
||
depth -= 1
|
||
if depth == 0:
|
||
return src[start:pos + 1]
|
||
return ""
|
||
|
||
|
||
def free_port() -> int:
|
||
with socket.socket() as probe:
|
||
probe.bind(("127.0.0.1", 0))
|
||
return probe.getsockname()[1]
|
||
|
||
|
||
def tcp_ok(host, port, timeout=6.0) -> bool:
|
||
sock = socket.socket()
|
||
sock.settimeout(timeout)
|
||
try:
|
||
sock.connect((str(host), int(port)))
|
||
return True
|
||
except Exception: # noqa: BLE001
|
||
return False
|
||
finally:
|
||
try:
|
||
sock.close()
|
||
except Exception: # noqa: BLE001
|
||
pass
|
||
|
||
|
||
def main() -> int:
|
||
from lanremote import discovery
|
||
from lanremote.config import Store
|
||
from lanremote.server import RemoteServer
|
||
from stub_support import StubUI, make_stub_actions
|
||
|
||
print("一、局域网发现的协议本身")
|
||
obj = json.loads(discovery.build_reply("测试电脑", 8765, "1.4.0")
|
||
.decode("utf-8"))
|
||
check("应答里有 magic", obj.get("lanremote") == discovery.REPLY_MAGIC, obj)
|
||
check("应答里有名字", obj.get("name") == "测试电脑", obj)
|
||
check("应答里有端口", int(obj.get("port") or 0) == 8765, obj)
|
||
|
||
probe = json.dumps({"lanremote": discovery.PROBE_MAGIC,
|
||
"proto": discovery.PROTOCOL}).encode()
|
||
check("探测包能被解析", discovery.parse_probe(probe) is not None)
|
||
check("乱码探测包被忽略", discovery.parse_probe(b"not json") is None)
|
||
check("伪造 magic 的包被忽略",
|
||
discovery.parse_probe(json.dumps({"lanremote": "x"}).encode())
|
||
is None)
|
||
|
||
print()
|
||
print("二、先起被控端实例,再广播搜它")
|
||
port = free_port()
|
||
store = Store(Path(tempfile.mkdtemp(prefix="lan_test_")))
|
||
store.set("port", port)
|
||
store.set("pairing_code", "482913")
|
||
ui = StubUI()
|
||
server = RemoteServer(store, make_stub_actions(ui, store), ui=ui)
|
||
server.start()
|
||
time.sleep(1.2)
|
||
check("被控端起来了", True, port)
|
||
|
||
found = []
|
||
try:
|
||
found = discovery.discover(timeout=3.0)
|
||
except Exception as exc: # noqa: BLE001
|
||
print(f" 搜索异常: {exc}")
|
||
listing = [f"{item.get('host')}:{item.get('port')}" for item in found[:5]]
|
||
print(f" 广播搜到 {len(found)} 台: {listing}")
|
||
|
||
mine = [item for item in found if int(item.get("port") or 0) == port]
|
||
if mine:
|
||
check("广播搜到了自己起的实例(UDP 应答正常)", True, listing)
|
||
target = mine[0]
|
||
check("搜到的名字不是空的", bool(target.get("name")), target)
|
||
else:
|
||
# UDP 8766 被别的 agent 占着时会出现这种情况(单独跑就是)。
|
||
# 那就退一步:验证搜索机制能返回结果、且能直连。
|
||
check("广播能返回结果(8766 可能被别的实例占用)",
|
||
len(found) >= 1, listing)
|
||
target = found[0] if found else None
|
||
|
||
if target is not None:
|
||
print(f" 对 {target.get('host')}:{target.get('port')} 做 TCP 直连")
|
||
check("搜到之后能直接 TCP 连上(不经中转)",
|
||
tcp_ok(target.get("host"), target.get("port")), target)
|
||
|
||
print()
|
||
print("三、本实例的 TCP 端口是开的(直连能进)")
|
||
check("测试实例端口可直连", tcp_ok("127.0.0.1", port), port)
|
||
|
||
try:
|
||
server.stop()
|
||
except Exception: # noqa: BLE001
|
||
pass
|
||
|
||
print()
|
||
print("四、安卓端源码里有这些新东西")
|
||
src = MAIN.read_text(encoding="utf-8")
|
||
code = re.sub(r"//[^\n]*", "", src)
|
||
code = re.sub(r"/\*.*?\*/", "", code, flags=re.S)
|
||
|
||
check("有局域网页面(buildLanPanel)",
|
||
"private void buildLanPanel()" in code)
|
||
check("能显示局域网页面", "private void showLanPanel()" in code)
|
||
check("有自动搜索", "private void startLanSearch()" in code)
|
||
check("首页有局域网入口按钮",
|
||
'bigButton("局域网连接(同一个 WiFi)"' in code)
|
||
check("局域网页面能返回", "private void hideLanPanel()" in code)
|
||
check("返回键会先退出局域网页面", "closeLanIfOpen()" in code)
|
||
check("用到了 Discovery.search(广播搜索)", "Discovery.search(" in code)
|
||
check("用到了 DiscoveryCore.Found(结果类型)",
|
||
"DiscoveryCore.Found" in code)
|
||
|
||
check("有服务器延迟检测", "private void checkServer()" in code)
|
||
check("首页有检查服务器按钮", '"检查服务器"' in code)
|
||
check("延迟结果显示在首页", "serverStatus" in code)
|
||
check("延迟按快慢变色", "ms < 300" in code and "C_DANGER" in code)
|
||
|
||
print()
|
||
print("五、局域网这条路不碰中转")
|
||
body = java_method(code, "private void connectLanTyped()")
|
||
check("connectLanTyped 方法体取到了", len(body) > 200, len(body))
|
||
print(f" 方法体 {len(body)} 字符")
|
||
check("没用 relayUrl(不走中转)", "relayUrl" not in body, body[:120])
|
||
check("没走 connectViaRelay", "connectViaRelay" not in body)
|
||
check("调的是直连 connect(", "connect(host, port, code" in body,
|
||
body[:200])
|
||
check("记住配对码(便于回退中转)", "rememberPairingCode(code)" in body)
|
||
check("断开后会自动切回中转", "lanDirect = true" in body)
|
||
|
||
print()
|
||
print("=" * 62)
|
||
print(f"通过 {passed} 项,失败 {failed} 项")
|
||
return 0 if failed == 0 else 1
|
||
|
||
|
||
if __name__ == "__main__":
|
||
raise SystemExit(main())
|