1
0
mirror of git://f0xx.org/android_cast synced 2026-07-29 08:37:37 +03:00

sync on be, vpn

This commit is contained in:
Anton Afanasyeu
2026-06-13 15:31:18 +02:00
parent f9b73b48da
commit 86055bf509
42 changed files with 2472 additions and 917 deletions

View File

@@ -57,19 +57,28 @@ public final class DevVpnStatusProbe {
tunnelLevel = DevNetworkSelfTestReport.Level.PASS;
} else if (RemoteAccessStatusStore.STATE_FAILURE.equals(tunnelState)) {
tunnelLevel = DevNetworkSelfTestReport.Level.FAIL;
} else if (RemoteAccessStatusStore.STATE_WAIT.equals(last.state)
&& isAwaitingWhitelist(last.detail)) {
tunnelLevel = DevNetworkSelfTestReport.Level.PASS;
} else {
tunnelLevel = DevNetworkSelfTestReport.Level.WARN;
}
r.item(tunnelLevel, "tunnel-state", tunnelState);
String tunnelLabel = formatTunnelStateLabel(tunnelState, last);
r.item(tunnelLevel, "tunnel-state", tunnelLabel);
if (mode != RemoteAccessMode.DISABLED
&& !RemoteAccessStatusStore.STATE_OFF.equals(controlPlane)) {
DevNetworkSelfTestReport.Level cpLevel =
RemoteAccessStatusStore.STATE_FAILURE.equals(controlPlane)
? DevNetworkSelfTestReport.Level.FAIL
: RemoteAccessStatusStore.STATE_SUCCESS.equals(controlPlane)
? DevNetworkSelfTestReport.Level.PASS
: DevNetworkSelfTestReport.Level.WARN;
DevNetworkSelfTestReport.Level cpLevel;
if (controlPlane.startsWith("ok (")) {
cpLevel = DevNetworkSelfTestReport.Level.PASS;
} else if (RemoteAccessStatusStore.STATE_FAILURE.equals(last.state)
&& RemoteAccessFailureReason.isControlPlaneMethod(last.method)) {
cpLevel = DevNetworkSelfTestReport.Level.FAIL;
} else if (RemoteAccessStatusStore.STATE_SUCCESS.equals(last.state)) {
cpLevel = DevNetworkSelfTestReport.Level.PASS;
} else {
cpLevel = DevNetworkSelfTestReport.Level.WARN;
}
r.item(cpLevel, "control-plane", controlPlane);
}
@@ -172,6 +181,18 @@ public final class DevVpnStatusProbe {
}
private static String resolveControlPlaneState(RemoteAccessStatusStore.Snapshot last) {
if (RemoteAccessStatusStore.STATE_WAIT.equals(last.state)) {
if (isAwaitingWhitelist(last.detail)) {
return "ok (awaiting whitelist)";
}
if ("no_pending_session".equals(last.detail)) {
return "ok (awaiting operator session)";
}
if ("rate_limited".equals(last.detail)) {
return "ok (poll rate limited)";
}
return last.detail.isEmpty() ? RemoteAccessStatusStore.STATE_WAIT : last.detail;
}
if (!RemoteAccessFailureReason.isControlPlaneMethod(last.method)) {
if (RemoteAccessStatusStore.STATE_IDLE.equals(last.state)
|| RemoteAccessStatusStore.STATE_SUCCESS.equals(last.state)) {
@@ -182,6 +203,22 @@ public final class DevVpnStatusProbe {
return last.state;
}
private static boolean isAwaitingWhitelist(String detail) {
return "not_whitelisted".equals(detail);
}
private static String formatTunnelStateLabel(String tunnelState, RemoteAccessStatusStore.Snapshot last) {
if (RemoteAccessStatusStore.STATE_WAIT.equals(last.state)) {
if (isAwaitingWhitelist(last.detail)) {
return "idle (awaiting whitelist — no tunnel expected)";
}
if ("no_pending_session".equals(last.detail)) {
return "idle (awaiting operator open session)";
}
}
return tunnelState;
}
private static String resolveDisplayedFailReason(
Context context,
RemoteAccessMode mode,
@@ -191,10 +228,12 @@ public final class DevVpnStatusProbe {
if (mode == RemoteAccessMode.DISABLED) {
return "";
}
if (!RemoteAccessStatusStore.STATE_FAILURE.equals(last.state)) {
return "";
}
String expanded = RemoteAccessFailureReason.expandForDisplay(context, last.method, last.failReason);
if (RemoteAccessFailureReason.isControlPlaneMethod(last.method)
&& RemoteAccessStatusStore.STATE_FAILURE.equals(last.state)) {
if (RemoteAccessFailureReason.isControlPlaneMethod(last.method)) {
if (!RemoteAccessStatusStore.STATE_SUCCESS.equals(tunnelState)) {
return "[heartbeat] " + expanded;
}
@@ -204,8 +243,7 @@ public final class DevVpnStatusProbe {
&& RemoteAccessStatusStore.STATE_FAILURE.equals(tunnelState)) {
return "[tunnel] " + expanded;
}
if (RemoteAccessStatusStore.STATE_FAILURE.equals(controlPlane)
&& !expanded.isEmpty()) {
if (!expanded.isEmpty()) {
return "[heartbeat] " + expanded;
}
return "";

View File

@@ -14,7 +14,7 @@ public final class RemoteAccessFailureReason {
public static String fromPollException(Context context, Exception e) {
String host = heartbeatHost(context);
if (e instanceof SocketTimeoutException) {
return "heartbeat HTTP timeout — device→" + host + " (15s connect/read)";
return "heartbeat HTTP timeout — device→" + host + " (30s connect/read)";
}
if (e instanceof UnknownHostException) {
return "heartbeat DNS failed — " + host + " (" + safeMsg(e) + ")";

View File

@@ -18,7 +18,7 @@ import java.nio.charset.StandardCharsets;
/** POST heartbeat type:ra to BE (shared by RemoteAccessService). */
public final class RemoteAccessHeartbeatClient {
private static final String TAG = "RemoteAccessHB";
private static final int HTTP_TIMEOUT_MS = 15_000;
private static final int HTTP_TIMEOUT_MS = 30_000;
private RemoteAccessHeartbeatClient() {}

View File

@@ -170,11 +170,12 @@ public final class RemoteAccessService extends Service {
RemoteAccessStatusStore.INITIATOR_BE,
raAction, resp.optString("session_id", ""));
} else {
String waitReason = resp.optString("reason", "");
RemoteAccessStatusStore.record(
this, mode, RemoteAccessStatusStore.STATE_IDLE,
this, mode, RemoteAccessStatusStore.STATE_WAIT,
"RemoteAccessService.runPoll",
RemoteAccessStatusStore.INITIATOR_DEVICE,
"", resp.optString("session_id", ""));
RemoteAccessStatusStore.INITIATOR_BE,
"", waitReason, resp.optString("session_id", ""));
}
} catch (Exception e) {
Log.w(TAG, "poll failed: " + e.getMessage());

View File

@@ -20,12 +20,15 @@ public final class RemoteAccessStatusStore {
public static final String STATE_FAILURE = "failure";
public static final String STATE_CONNECTING = "connecting";
public static final String STATE_IDLE = "idle";
public static final String STATE_WAIT = "wait";
public static final String STATE_OFF = "off";
public static final String INITIATOR_DEVICE = "device";
public static final String INITIATOR_BE = "backend";
public static final String INITIATOR_USER = "user";
private static final String KEY_DETAIL = "detail";
private RemoteAccessStatusStore() {}
public static void record(
@@ -36,6 +39,18 @@ public final class RemoteAccessStatusStore {
String initiator,
String failReason,
String sessionId) {
record(context, mode, state, method, initiator, failReason, "", sessionId);
}
public static void record(
Context context,
RemoteAccessMode mode,
String state,
String method,
String initiator,
String failReason,
String detail,
String sessionId) {
String type = mode == null || mode == RemoteAccessMode.DISABLED
? "off" : mode.name().toLowerCase();
prefs(context).edit()
@@ -44,6 +59,7 @@ public final class RemoteAccessStatusStore {
.putString(KEY_METHOD, method != null ? method : "")
.putString(KEY_INITIATOR, initiator != null ? initiator : "")
.putString(KEY_FAIL_REASON, failReason != null ? failReason : "")
.putString(KEY_DETAIL, detail != null ? detail : "")
.putString(KEY_SESSION_ID, sessionId != null ? sessionId : "")
.putLong(KEY_UPDATED_MS, System.currentTimeMillis())
.apply();
@@ -57,6 +73,7 @@ public final class RemoteAccessStatusStore {
p.getString(KEY_METHOD, ""),
p.getString(KEY_INITIATOR, ""),
p.getString(KEY_FAIL_REASON, ""),
p.getString(KEY_DETAIL, ""),
p.getString(KEY_SESSION_ID, ""),
p.getLong(KEY_UPDATED_MS, 0L));
}
@@ -71,6 +88,7 @@ public final class RemoteAccessStatusStore {
public final String method;
public final String initiator;
public final String failReason;
public final String detail;
public final String sessionId;
public final long updatedMs;
@@ -80,6 +98,7 @@ public final class RemoteAccessStatusStore {
String method,
String initiator,
String failReason,
String detail,
String sessionId,
long updatedMs) {
this.type = type != null ? type : "off";
@@ -87,6 +106,7 @@ public final class RemoteAccessStatusStore {
this.method = method != null ? method : "";
this.initiator = initiator != null ? initiator : "";
this.failReason = failReason != null ? failReason : "";
this.detail = detail != null ? detail : "";
this.sessionId = sessionId != null ? sessionId : "";
this.updatedMs = updatedMs;
}