Files
ykxmz/_build/patch_lan_fallback.py
T
xmz7891 b705216e4a ykxmz 1.5.0锛氫慨澶嶆墜琛ㄧ TLS 璇佷功鏍¢獙 + MTU 淇缃戠粶绋冲畾鎬?
琚帶绔?- 淇 MTU 闂锛氬す MSS + 璺緞 MTU 鎺㈡祴锛堝叕缃戝彲鐢ㄧ巼 48% -> 100%锛?- 澶嶇敤 HTTP 杩炴帴锛堝厤鎺夋瘡娆℃柊寤?TLS 鐨?30% 鎻℃墜澶辫触锛?- 姣忓垎閽熷洖澶存壘灞€鍩熺綉锛岃嚜鍔ㄥ垏鍥炲揩 400 鍊嶇殑璺緞
- 鐢婚潰蹇冭烦甯э細闈欐鏃剁渷娴侀噺锛屽鎴风浠嶇煡閬撴祦鏄椿鐨?- 閿佸睆鏃剁粰鍑哄彲鎿嶄綔鐨勬彁绀?
鎵嬭〃绔?- 鍐呯疆 GTS Root R4 / GlobalSign Root CA锛屼慨 SSLHandshakeException
- 杩炴帴閿欒缈昏瘧鎴愪汉璇濓紙璇佷功/鏃堕棿/瑙f瀽/瓒呮椂鍒嗗埆鎻愮ず锛?- 缁忎腑杞繛涓婂悗鐢ㄦ湇鍔″櫒鎶ョ殑鍦板潃鍒锋柊宸查厤瀵硅褰?- 鏂板灞€鍩熺綉杩炴帴椤甸潰銆佹湇鍔″櫒寤惰繜妫€娴?
鏈嶅姟鍣ㄧ
- 鏀寔 chunked 璇锋眰浣擄紙淇瘡 16 绉掍竴娆$殑杩炴帴閿欎贡涓庡ぇ闈㈢Н 502锛?- 缃戠粶璋冧紭鑴氭湰 net-tune.sh锛堝紑鏈鸿嚜鍔ㄥ簲鐢級
- 绠$悊椤碉細鎵归噺鍒犻櫎銆佺綉缁滀綋妫€銆佷笅杞藉尯
- 闅ч亾鏀?HTTP/2 + 鍙岃繛鎺?
鏂囨。
- 璁稿彲鍗忚 / 瀹夎鍓嶅繀璇?/ 瀹夎鍚庨』鐭ワ紙浣滆€咃細灏忛害瀛愶級
2026-10-06 19:01:05 +08:00

309 lines
12 KiB
Python

# -*- coding: utf-8 -*-
"""安卓端:局域网断了就无缝切回中转服务器。
用户要求:
"检测到局域网连不上了,就无缝链接到中转服务器"
场景:
手表和电脑本来在同一 WiFi,走局域网直连(快、稳)。
然后手表走出 WiFi 范围了 / 电脑换了网络 / WiFi 断了。
→ 应该**自动**切回中转,用户不用管。
做法:
1. 记住"当前是局域网直连"以及连的是谁
2. onDisconnected 时,如果刚才走的是局域网 -> 自动经中转重连
3. 反过来:中转也断了就重试几次,别立刻放弃
4. 全程给用户提示,但不能弹回连接页打断操作
"""
from __future__ import annotations
import sys
from pathlib import Path
MAIN = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote\android\src"
r"\com\lanremote\watch\MainActivity.java")
# ---------- 1. 加状态字段 ----------
FIELD_OLD = ''' private void connect(final String host, final int port, final String code,
final String token, final String key) {
if (busy) {
return;
}'''
FIELD_NEW = ''' // ---- 断线自动切换用的状态 ----
/** 当前是不是走局域网直连(断了要切回中转)。 */
private volatile boolean lanDirect;
/** 刚才连的地址/配对码/令牌,切回中转时要用。 */
private volatile String lastHost = "";
private volatile int lastPort;
private volatile String lastCode = "";
private volatile String lastToken = "";
/** 正在自动切换中,避免重入。 */
private volatile boolean autoSwitching;
/** 自动重试次数,防止无限刷屏。 */
private int autoRetry;
private void connect(final String host, final int port, final String code,
final String token, final String key) {
if (busy) {
return;
}'''
# ---------- 2. connect 时记录状态 ----------
REC_OLD = ''' busy = true;
setStatus("正在连接 " + host + ":" + port + " …", C_WARN);
appendLog("连接 " + host + ":" + port);'''
REC_NEW = ''' busy = true;
// 记下来:断线时要用这些信息切回中转 / 重连
lastHost = host;
lastPort = port;
if (code != null) {
lastCode = code;
}
if (token != null) {
lastToken = token;
}
setStatus("正在连接 " + host + ":" + port + " …", C_WARN);
appendLog("连接 " + host + ":" + port);'''
# ---------- 3. 成功连上后标记是不是局域网 ----------
MODE_OLD = ''' if (serverLabel != null) {
serverLabel.setText("已连接 " + (finalName == null ? host : finalName));
}'''
MODE_NEW = ''' // 记住这次是不是局域网直连 ——
// 局域网断了要自动切回中转,靠的就是这个标记。
lanDirect = finalLanDirect;
autoRetry = 0;
if (serverLabel != null) {
serverLabel.setText("已连接 "
+ (finalName == null ? host : finalName)
+ (finalLanDirect ? "(局域网)" : "(中转)"));
}'''
# 把"是不是局域网"这个判断结果传出来
LAN_FLAG_OLD = ''' String error = null;
String newToken = null;
String serverName = null;
boolean ok = false;'''
LAN_FLAG_NEW = ''' String error = null;
String newToken = null;
String serverName = null;
boolean ok = false;
// 这次连上的是局域网还是中转(决定断线后怎么救)
boolean usedLan = !relayUrl().isEmpty() ? false : true;'''
# 直连成功时置 true
DIRECT_OK_OLD = ''' appendLog("已切换为局域网直连:" + directIp
+ ":" + directPort);'''
DIRECT_OK_NEW = ''' appendLog("已切换为局域网直连:" + directIp
+ ":" + directPort);
usedLan = true;'''
# 退回中转时置 false
FALLBACK_OLD = ''' appendLog("直连失败,退回中转:"
+ Json.str(direct, "error", "未知原因"));'''
FALLBACK_NEW = ''' appendLog("直连失败,退回中转:"
+ Json.str(direct, "error", "未知原因"));
usedLan = false;'''
# final 变量
FINAL_OLD = ''' final boolean success = ok;
final String finalError = error;
final String finalToken = newToken;
final String finalName = serverName;'''
FINAL_NEW = ''' final boolean success = ok;
final String finalError = error;
final String finalToken = newToken;
final String finalName = serverName;
final boolean finalLanDirect = usedLan && ok;'''
# ---------- 4. onDisconnected 自动切回中转 ----------
DISC_OLD = ''' public void onDisconnected(final String reason) {
// 换连另一台电脑后,「功能」页不能还显示上一台的分组
featureCache = null;
featureGroups = null; ui.post(new Runnable() {'''
DISC_NEW = ''' public void onDisconnected(final String reason) {
// 换连另一台电脑后,「功能」页不能还显示上一台的分组
featureCache = null;
featureGroups = null;
// ★ 局域网断了 -> 无缝切回中转服务器。
// 用户从 WiFi 走出去、或者电脑换了网络,都会走到这里。
// 不打断操作,自动接上。
if (lanDirect && !autoSwitching) {
String relay = relayUrl();
if (!relay.isEmpty()) {
autoSwitching = true;
appendLog("局域网断了(" + reason + "),正在切到中转服务器…");
ui.post(new Runnable() {
@Override
public void run() {
setStatus("局域网断了,正在切到中转服务器…", C_WARN);
}
});
ui.postDelayed(new Runnable() {
@Override
public void run() {
switchToRelay();
}
}, 600);
return;
}
appendLog("局域网断了,但没有配中转地址,只能断开");
}
// 中转也断了:重试几次再放弃(这条线路本来就会抖)
if (!lanDirect && autoRetry < 3 && !autoSwitching) {
autoRetry++;
appendLog("中转断了(" + reason + "),第 " + autoRetry + " 次自动重连…");
ui.post(new Runnable() {
@Override
public void run() {
setStatus("中转断了,正在重连(第 " + autoRetry + " 次)…", C_WARN);
}
});
ui.postDelayed(new Runnable() {
@Override
public void run() {
switchToRelay();
}
}, 700 * autoRetry);
return;
}
autoRetry = 0; ui.post(new Runnable() {'''
DISC_TAIL_OLD = ''' appendLog("断开:" + reason);
}
});
}'''
DISC_TAIL_NEW = ''' appendLog("断开:" + reason);
lanDirect = false;
}
});
}
/**
* 经中转重连(局域网断了、或者中转抖了之后自动调用)。
*
* 用后台线程做,不阻塞界面;成功了就继续用,失败才弹回连接页。
*/
private void switchToRelay() {
final String relay = relayUrl();
if (relay.isEmpty()) {
autoSwitching = false;
return;
}
final String code = lastCode;
final String token = lastToken;
io.execute(new Runnable() {
@Override
public void run() {
String error = null;
boolean ok = false;
String newToken = token;
String name = lastHost;
try {
Map<String, Object> reply = client.connectViaRelay(
relay, code, token, MainActivity.this, 40000);
ok = Json.bool(reply, "ok", false);
if (ok) {
newToken = Json.str(reply, "token",
token == null ? "" : token);
name = Json.str(reply, "serverName", lastHost);
} else {
error = Json.str(reply, "error", "中转连接被拒");
}
} catch (final IOException exc) {
error = describeNetworkError(exc, relay);
}
final boolean success = ok;
final String finalError = error;
final String finalToken = newToken;
final String finalName = name;
final String usedCode = code;
ui.post(new Runnable() {
@Override
public void run() {
autoSwitching = false;
if (success) {
lanDirect = false;
lastToken = finalToken;
if (finalToken != null && !finalToken.isEmpty()) {
store.saveDevice(
DeviceStore.deviceKey(lastHost, lastPort,
store.deviceId()),
finalName == null ? lastHost : finalName,
lastHost, lastPort, finalToken);
refreshDeviceList();
}
if (serverLabel != null) {
serverLabel.setText("已连接 "
+ (finalName == null ? lastHost : finalName)
+ "(中转)");
}
appendLog("已切到中转服务器,连接恢复");
setStatus("已切到中转(局域网不可用)", C_OK);
showControlPanel();
} else {
autoRetry = 0;
lanDirect = false;
setStatus("中转也连不上:" + finalError, C_DANGER);
appendLog("切中转失败:" + finalError);
showConnectPanel();
}
}
});
}
});
}'''
def patch(pairs, label: str) -> bool:
text = MAIN.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}")
MAIN.write_text(text, encoding="utf-8", newline="\n")
return ok
def main() -> int:
text = MAIN.read_text(encoding="utf-8")
if "switchToRelay" in text:
print(" 已经加过自动切中转")
return 0
ok = patch([
(FIELD_OLD, FIELD_NEW, "加自动切换状态字段"),
(REC_OLD, REC_NEW, "connect 记录状态"),
(LAN_FLAG_OLD, LAN_FLAG_NEW, "加 usedLan 标记"),
(DIRECT_OK_OLD, DIRECT_OK_NEW, "直连成功置 true"),
(FALLBACK_OLD, FALLBACK_NEW, "退回中转置 false"),
(FINAL_OLD, FINAL_NEW, "传出 finalLanDirect"),
(MODE_OLD, MODE_NEW, "连上后标记模式"),
(DISC_OLD, DISC_NEW, "断线自动切中转"),
(DISC_TAIL_OLD, DISC_TAIL_NEW, "switchToRelay 方法"),
], "MainActivity")
return 0 if ok else 1
if __name__ == "__main__":
sys.exit(main())