fix(companion): guarantee dual-path peering — LAN p2p + public anchor, always
The whole point of FIPS: the phone peers with the node's npub using the LAN endpoint as a direct p2p dial hint AND rendezvouses via a public anchor when away — neither LAN nor 5G location may matter. The anchor half only existed when the scanned QR carried fanchors, so pairing against an older node left the phone LAN-only and everything died on 5G. The Archipelago vps2 anchor (npub + 146.59.87.168:8444/tcp, lockstep with core fips/anchors.rs) is now baked into upsertNodePeer as a guaranteed peer. Mesh connect retry window widened so a first-ever pairing survives the VPN consent dialog. Served APK: 0.5.3 (vc23). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,16 @@ import androidx.datastore.preferences.preferencesDataStore
|
||||
|
||||
private val Context.fipsDataStore: DataStore<Preferences> by preferencesDataStore(name = "fips_prefs")
|
||||
|
||||
// Archipelago-operated public anchor (vps2). Baked in so EVERY pairing yields
|
||||
// both paths — direct LAN p2p to the node AND a public rendezvous for
|
||||
// away-from-home — even when the scanned node is old enough that its QR
|
||||
// carries no fanchors. Keep in lockstep with
|
||||
// core/archipelago/src/fips/anchors.rs (ARCHY_ANCHOR_*).
|
||||
internal const val ARCHY_ANCHOR_NPUB =
|
||||
"npub1dptaktwxv0mm245g2lqjykwm5ll0jpc6m3r4242ydfa9z7qe6urs3jvrak"
|
||||
internal const val ARCHY_ANCHOR_ADDR = "146.59.87.168:8444"
|
||||
internal const val ARCHY_ANCHOR_TRANSPORT = "tcp"
|
||||
|
||||
/**
|
||||
* Mesh identity + known node peers. Follows the same plaintext-DataStore
|
||||
* storage model as ServerPreferences (the server password lives there the
|
||||
@@ -91,6 +101,21 @@ class FipsPreferences(private val context: Context) {
|
||||
}))
|
||||
}
|
||||
}
|
||||
// Guarantee the public anchor: without it, a QR from an older node
|
||||
// leaves the phone LAN-only and pairing/connecting dies off-LAN.
|
||||
if (info.npub != ARCHY_ANCHOR_NPUB &&
|
||||
incoming.none { it.optString("npub") == ARCHY_ANCHOR_NPUB }
|
||||
) {
|
||||
incoming += JSONObject().apply {
|
||||
put("npub", ARCHY_ANCHOR_NPUB)
|
||||
put("alias", "Archipelago anchor")
|
||||
put("addresses", JSONArray().put(JSONObject().apply {
|
||||
put("transport", ARCHY_ANCHOR_TRANSPORT)
|
||||
put("addr", ARCHY_ANCHOR_ADDR)
|
||||
put("priority", 40)
|
||||
}))
|
||||
}
|
||||
}
|
||||
val incomingNpubs = incoming.map { it.optString("npub") }.toSet()
|
||||
context.fipsDataStore.edit { prefs ->
|
||||
val current = JSONArray(prefs[peersKey] ?: "[]")
|
||||
|
||||
@@ -185,8 +185,10 @@ fun ServerConnectScreen(
|
||||
useHttps = false,
|
||||
port = "",
|
||||
)
|
||||
// The tunnel + mesh route need a moment on cold start.
|
||||
for (attempt in 0 until 4) {
|
||||
// The tunnel + mesh route need a moment on cold start — and on
|
||||
// a first-ever pairing the VPN consent dialog is on screen at
|
||||
// the same time, so give the user time to tap it.
|
||||
for (attempt in 0 until 6) {
|
||||
if (attempt > 0) delay(2000)
|
||||
reachable = testConnection(meshServer)
|
||||
if (reachable) break
|
||||
|
||||
Reference in New Issue
Block a user