mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 23:00:44 +00:00
琚帶绔?- 淇 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 + 鍙岃繛鎺? 鏂囨。 - 璁稿彲鍗忚 / 瀹夎鍓嶅繀璇?/ 瀹夎鍚庨』鐭ワ紙浣滆€咃細灏忛害瀛愶級
274 lines
12 KiB
Python
274 lines
12 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""安卓端改造:
|
|
|
|
用户要求:
|
|
1. 去掉老版本那些「搜索局域网」的东西
|
|
2. 如果发现电脑和手表在同一个网络 -> 自动切局域网直连
|
|
3. 不在同一网络但连上了 -> 继续用中转服务器
|
|
|
|
实现:
|
|
A. RelayTransport 接入时把中转给的 lanIps / port 记下来
|
|
B. RemoteClient connectViaRelay 成功后把这两个值留给界面
|
|
C. MainActivity - 中转连上之后判断同不同网段,同就自动切直连
|
|
- 删掉「自动搜索电脑」按钮和 startDiscovery()
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote")
|
|
WATCH = ROOT / "android" / "src" / "com" / "lanremote" / "watch"
|
|
RELAY_T = WATCH / "RelayTransport.java"
|
|
CLIENT = WATCH / "RemoteClient.java"
|
|
MAIN = WATCH / "MainActivity.java"
|
|
|
|
|
|
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
|
|
|
|
|
|
# ================= A. RelayTransport =================
|
|
|
|
RT_FIELD_OLD = ''' session = Json.str(reply, "session", "");
|
|
deviceName = Json.str(reply, "deviceName", "");'''
|
|
|
|
RT_FIELD_NEW = ''' session = Json.str(reply, "session", "");
|
|
deviceName = Json.str(reply, "deviceName", "");
|
|
// 中转顺便告诉我们「这台电脑在哪个局域网、开在哪个端口」。
|
|
// 手表拿它判断要不要切成局域网直连。
|
|
lanIps = Json.stringList(reply, "lanIps");
|
|
lanPort = Json.integer(reply, "port", 0);'''
|
|
|
|
RT_GETTER_OLD = ''' public boolean attach() {'''
|
|
|
|
RT_GETTER_NEW = ''' /** 被控端上报的局域网 IP(可能多个网卡)。判断同网段用。 */
|
|
private java.util.List<String> lanIps = new java.util.ArrayList<String>();
|
|
|
|
/** 被控端监听端口。0 表示它没报(那就没法直连)。 */
|
|
private int lanPort;
|
|
|
|
public java.util.List<String> getLanIps() {
|
|
return lanIps;
|
|
}
|
|
|
|
public int getLanPort() {
|
|
return lanPort;
|
|
}
|
|
|
|
public boolean attach() {'''
|
|
|
|
# ================= B. RemoteClient =================
|
|
|
|
RC_FIELD_OLD = ''' public Map<String, Object> connectViaRelay(String baseUrl, String code,
|
|
String token, Listener listener,
|
|
int timeoutMs) throws IOException {
|
|
close();'''
|
|
|
|
RC_FIELD_NEW = ''' /** 上次经中转接入时,被控端报的局域网 IP 和端口。 */
|
|
private java.util.List<String> relayLanIps = new java.util.ArrayList<String>();
|
|
private int relayLanPort;
|
|
|
|
public java.util.List<String> relayLanIps() {
|
|
return relayLanIps;
|
|
}
|
|
|
|
public int relayLanPort() {
|
|
return relayLanPort;
|
|
}
|
|
|
|
public Map<String, Object> connectViaRelay(String baseUrl, String code,
|
|
String token, Listener listener,
|
|
int timeoutMs) throws IOException {
|
|
close();
|
|
relayLanIps = new java.util.ArrayList<String>();
|
|
relayLanPort = 0;'''
|
|
|
|
RC_TAIL_OLD = ''' return startTransport(relay, code, token, listener, timeoutMs);
|
|
}'''
|
|
|
|
RC_TAIL_NEW = ''' Map<String, Object> reply =
|
|
startTransport(relay, code, token, listener, timeoutMs);
|
|
if (Json.bool(reply, "ok", false)) {
|
|
// 留给界面判断:要不要切成局域网直连
|
|
relayLanIps = relay.getLanIps();
|
|
relayLanPort = relay.getLanPort();
|
|
}
|
|
return reply;
|
|
}'''
|
|
|
|
# ================= C. MainActivity =================
|
|
|
|
# C1. 删掉「自动搜索电脑」按钮
|
|
MAIN_BTN_OLD = ''' Button search = bigButton("自动搜索电脑", C_ACCENT, 19);'''
|
|
|
|
MAIN_BTN_NEW = ''' // 老版本的「自动搜索电脑」按钮去掉了:
|
|
// 现在统一走中转,连上之后程序自己判断要不要切成局域网直连。
|
|
Button search = null;
|
|
if (false) {'''
|
|
|
|
# C2. 中转连上后判断同网段
|
|
MAIN_CONNECT_OLD = ''' ok = Json.bool(reply, "ok", false);
|
|
if (ok) {
|
|
newToken = Json.str(reply, "token", token == null ? "" : token);
|
|
serverName = Json.str(reply, "serverName", host);
|
|
} else {'''
|
|
|
|
MAIN_CONNECT_NEW = ''' ok = Json.bool(reply, "ok", false);
|
|
if (ok) {
|
|
newToken = Json.str(reply, "token", token == null ? "" : token);
|
|
serverName = Json.str(reply, "serverName", host);
|
|
|
|
// ★ 经中转连上之后,看看电脑是不是和我们在同一个网络。
|
|
// 是的话就切成局域网直连 —— 快得多(几十毫秒 vs 几百毫秒),
|
|
// 而且不消耗流量、不怕隧道抖。
|
|
if (!relay.isEmpty()) {
|
|
String directIp = pickSameSubnet(client.relayLanIps());
|
|
int directPort = client.relayLanPort();
|
|
if (directIp != null && directPort > 0) {
|
|
appendLog("电脑和手表在同一网络(" + directIp
|
|
+ "),切换成局域网直连");
|
|
client.close();
|
|
Map<String, Object> direct = client.connect(
|
|
directIp, directPort, code, newToken,
|
|
MainActivity.this, 8000);
|
|
if (Json.bool(direct, "ok", false)) {
|
|
reply = direct;
|
|
newToken = Json.str(direct, "token",
|
|
newToken == null ? "" : newToken);
|
|
serverName = Json.str(direct, "serverName",
|
|
directIp);
|
|
appendLog("已切换为局域网直连:" + directIp
|
|
+ ":" + directPort);
|
|
} else {
|
|
// 直连没成(可能不在同一网段,只是网段巧合)。
|
|
// 退回中转,不要让用户连不上。
|
|
appendLog("直连失败,退回中转:"
|
|
+ Json.str(direct, "error", "未知原因"));
|
|
reply = client.connectViaRelay(relay, code,
|
|
newToken, MainActivity.this, 40000);
|
|
ok = Json.bool(reply, "ok", false);
|
|
if (ok) {
|
|
newToken = Json.str(reply, "token",
|
|
newToken == null ? "" : newToken);
|
|
serverName = Json.str(reply, "serverName",
|
|
directIp);
|
|
} else {
|
|
error = Json.str(reply, "error", "退回中转也失败");
|
|
}
|
|
}
|
|
} else {
|
|
appendLog("电脑不在同一网络,继续用中转");
|
|
}
|
|
}
|
|
} else {'''
|
|
|
|
# C3. 判断同网段的辅助方法
|
|
MAIN_HELPER_OLD = ''' private void connect(final String host, final int port, final String code,
|
|
final String token, final String key) {'''
|
|
|
|
MAIN_HELPER_NEW = ''' /** 手表自己在局域网里的 IPv4 地址(可能多张网卡)。拿不到就空。 */
|
|
private java.util.List<String> localIpv4List() {
|
|
java.util.List<String> found = new java.util.ArrayList<String>();
|
|
try {
|
|
java.util.Enumeration<java.net.NetworkInterface> interfaces =
|
|
java.net.NetworkInterface.getNetworkInterfaces();
|
|
while (interfaces != null && interfaces.hasMoreElements()) {
|
|
java.net.NetworkInterface nic = interfaces.nextElement();
|
|
if (nic == null || !nic.isUp() || nic.isLoopback()) {
|
|
continue;
|
|
}
|
|
java.util.Enumeration<java.net.InetAddress> addrs =
|
|
nic.getInetAddresses();
|
|
while (addrs != null && addrs.hasMoreElements()) {
|
|
java.net.InetAddress addr = addrs.nextElement();
|
|
if (addr instanceof java.net.Inet4Address
|
|
&& !addr.isLoopbackAddress()) {
|
|
String ip = addr.getHostAddress();
|
|
if (ip != null && !ip.startsWith("169.254.")
|
|
&& !found.contains(ip)) {
|
|
found.add(ip);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch (Exception ignored) {
|
|
// 权限不足之类,拿不到就算了 —— 那就不切换,继续用中转
|
|
}
|
|
return found;
|
|
}
|
|
|
|
/** 两个 IPv4 是不是同一个 /24 网段(家用网络基本都够用)。 */
|
|
private boolean sameSubnet(String a, String b) {
|
|
if (a == null || b == null) {
|
|
return false;
|
|
}
|
|
String[] left = a.split("\\\\.");
|
|
String[] right = b.split("\\\\.");
|
|
if (left.length != 4 || right.length != 4) {
|
|
return false;
|
|
}
|
|
return left[0].equals(right[0]) && left[1].equals(right[1])
|
|
&& left[2].equals(right[2]);
|
|
}
|
|
|
|
/**
|
|
* 从电脑报上来的局域网地址里,挑一个和手表同网段的。
|
|
*
|
|
* 挑不到就返回 null —— 表示不在同一个网络,继续走中转。
|
|
*/
|
|
private String pickSameSubnet(java.util.List<String> deviceIps) {
|
|
if (deviceIps == null || deviceIps.isEmpty()) {
|
|
return null;
|
|
}
|
|
java.util.List<String> mine = localIpv4List();
|
|
if (mine.isEmpty()) {
|
|
return null;
|
|
}
|
|
for (String deviceIp : deviceIps) {
|
|
for (String myIp : mine) {
|
|
if (sameSubnet(deviceIp, myIp)) {
|
|
return deviceIp;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private void connect(final String host, final int port, final String code,
|
|
final String token, final String key) {'''
|
|
|
|
|
|
def main() -> int:
|
|
ok = True
|
|
ok &= patch(RELAY_T, [
|
|
(RT_GETTER_OLD, RT_GETTER_NEW, "加 lanIps/lanPort 字段和取值"),
|
|
(RT_FIELD_OLD, RT_FIELD_NEW, "attach 里解析"),
|
|
], "RelayTransport")
|
|
|
|
ok &= patch(CLIENT, [
|
|
(RC_FIELD_OLD, RC_FIELD_NEW, "字段 + connectViaRelay 重置"),
|
|
(RC_TAIL_OLD, RC_TAIL_NEW, "成功后留下 lanIps"),
|
|
], "RemoteClient")
|
|
|
|
ok &= patch(MAIN, [
|
|
(MAIN_BTN_OLD, MAIN_BTN_NEW, "去掉「自动搜索电脑」按钮"),
|
|
(MAIN_HELPER_OLD, MAIN_HELPER_NEW, "加同网段判断方法"),
|
|
(MAIN_CONNECT_OLD, MAIN_CONNECT_NEW, "连上后自动切直连"),
|
|
], "MainActivity")
|
|
return 0 if ok else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|