diff --git a/app/src/main/kotlin/com/wisp/app/relay/OutboxRouter.kt b/app/src/main/kotlin/com/wisp/app/relay/OutboxRouter.kt index 5ac9a40..b8db04c 100644 --- a/app/src/main/kotlin/com/wisp/app/relay/OutboxRouter.kt +++ b/app/src/main/kotlin/com/wisp/app/relay/OutboxRouter.kt @@ -277,15 +277,6 @@ class OutboxRouter( targetedRelays.addAll(relayPool.getRelayUrls()) } - // Also query local relay for own notes - if (pubkey == relayPool.localRelayUserPubkey) { - val localUrl = relayPool.getLocalRelayUrl() - if (localUrl != null) { - relayPool.sendToLocalRelay(ClientMessage.req(subId, filter)) - targetedRelays.add(localUrl) - } - } - return targetedRelays } diff --git a/app/src/main/kotlin/com/wisp/app/relay/RelayConfig.kt b/app/src/main/kotlin/com/wisp/app/relay/RelayConfig.kt index a09ba2b..1e95d99 100644 --- a/app/src/main/kotlin/com/wisp/app/relay/RelayConfig.kt +++ b/app/src/main/kotlin/com/wisp/app/relay/RelayConfig.kt @@ -2,22 +2,11 @@ package com.wisp.app.relay import kotlinx.serialization.Serializable -enum class LocalRelayWritePolicy { OWN_NOTES, TAGGED, ALL_NOTES } - -@Serializable -data class LocalRelayConfig( - val url: String, - val enabled: Boolean = true, - val writePolicy: LocalRelayWritePolicy = LocalRelayWritePolicy.OWN_NOTES, - val kinds: Set = setOf(1, 1059, 9735) -) - enum class RelaySetType(val displayName: String, val eventKind: Int) { GENERAL("General", 10002), DM("DM", 10050), SEARCH("Search", 10007), - BLOCKED("Blocked", 10006), - LOCAL("Local", 0) + BLOCKED("Blocked", 10006) } @Serializable @@ -67,18 +56,5 @@ data class RelayConfig( return true } - private val LOCAL_HOST_REGEX = Regex( - "^ws://(" + - "localhost|" + - "127\\.0\\.0\\.1|" + - "10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" + - "192\\.168\\.\\d{1,3}\\.\\d{1,3}|" + - "172\\.(1[6-9]|2\\d|3[01])\\.\\d{1,3}\\.\\d{1,3}|" + - "[\\w.-]+:\\d+" + // any host with explicit port - ")(:\\d+)?(/.*)?$" - ) - - /** Returns true if the URL is a local/private relay (ws:// with localhost, loopback, or private IP). */ - fun isLocalRelayUrl(url: String): Boolean = LOCAL_HOST_REGEX.matches(url) } } diff --git a/app/src/main/kotlin/com/wisp/app/relay/RelayLifecycleManager.kt b/app/src/main/kotlin/com/wisp/app/relay/RelayLifecycleManager.kt index 0cf7012..bd9db50 100644 --- a/app/src/main/kotlin/com/wisp/app/relay/RelayLifecycleManager.kt +++ b/app/src/main/kotlin/com/wisp/app/relay/RelayLifecycleManager.kt @@ -97,7 +97,6 @@ class RelayLifecycleManager( Log.d("RLC", "[Lifecycle] onAppPause — connectedCount=${relayPool.connectedCount.value}") relayPool.appIsActive = false relayPool.healthTracker?.closeAllSessions() - relayPool.pauseLocalRelay() } /** @@ -112,7 +111,6 @@ class RelayLifecycleManager( // Set suppression window to prevent network-change reconnects from // firing shortly after this resume and causing a double reconnect. resumeReconnectUntilMs = System.currentTimeMillis() + RESUME_SUPPRESSION_MS - relayPool.resumeLocalRelay() reconnect(force = force) } diff --git a/app/src/main/kotlin/com/wisp/app/relay/RelayPool.kt b/app/src/main/kotlin/com/wisp/app/relay/RelayPool.kt index c900395..a4d9f8b 100644 --- a/app/src/main/kotlin/com/wisp/app/relay/RelayPool.kt +++ b/app/src/main/kotlin/com/wisp/app/relay/RelayPool.kt @@ -47,11 +47,6 @@ class RelayPool(private val prefs: SharedPreferences? = null) { private var blockedUrls = emptySet() fun getBlockedUrls(): Set = blockedUrls - // --- Local relay --- - private var localRelay: Relay? = null - private var localRelayConfig: LocalRelayConfig? = null - @Volatile var localRelayUserPubkey: String? = null - /** URLs tagged as recipient DM delivery relays (tier 2 for AUTH). */ private val dmDeliveryTargets: MutableSet = java.util.concurrent.ConcurrentHashMap.newKeySet() @@ -409,10 +404,6 @@ class RelayPool(private val prefs: SharedPreferences? = null) { } _events.tryEmit(msg.event) _relayEvents.tryEmit(RelayEvent(msg.event, relay.config.url, msg.subscriptionId)) - // Forward to local relay (fire-and-forget) - if (localRelay != null && relay !== localRelay && shouldForwardToLocalRelay(msg.event)) { - localRelay?.send(ClientMessage.event(msg.event)) - } subEventCounts.getOrPut(msg.subscriptionId) { java.util.concurrent.atomic.AtomicInteger(0) }.incrementAndGet() if (msg.subscriptionId.startsWith("feed")) { val count = ++feedEventCounter @@ -607,10 +598,6 @@ class RelayPool(private val prefs: SharedPreferences? = null) { if (isEvent && appIsActive) healthTracker?.onEventSent(relay.config.url, message.length) } } - // Also forward to local relay for own published events - if (isEvent && localRelay != null && localRelayConfig?.enabled == true) { - localRelay?.send(message) - } return sentCount } @@ -846,7 +833,7 @@ class RelayPool(private val prefs: SharedPreferences? = null) { */ fun connectEphemeralRelay(url: String) { if (url in blockedUrls) return - if (!RelayConfig.isValidUrl(url) && !RelayConfig.isLocalRelayUrl(url)) return + if (!RelayConfig.isValidUrl(url)) return if (ephemeralRelays.containsKey(url) || relayIndex.containsKey(url)) return if (ephemeralRelays.size >= MAX_EPHEMERAL) return ephemeralRelays.computeIfAbsent(url) { @@ -870,7 +857,7 @@ class RelayPool(private val prefs: SharedPreferences? = null) { ): Boolean { if (url in blockedUrls) return false if (!skipBadCheck && healthTracker?.isBad(url) == true) return false - if (!RelayConfig.isValidUrl(url) && !RelayConfig.isLocalRelayUrl(url)) return false + if (!RelayConfig.isValidUrl(url)) return false // Check cooldown for failed relays val cooldownUntil = relayCooldowns[url] @@ -1199,7 +1186,7 @@ class RelayPool(private val prefs: SharedPreferences? = null) { */ fun preConnectEphemeral(url: String) { if (url in blockedUrls) return - if (!RelayConfig.isValidUrl(url) && !RelayConfig.isLocalRelayUrl(url)) return + if (!RelayConfig.isValidUrl(url)) return if (ephemeralRelays.containsKey(url)) return if (ephemeralRelays.size >= MAX_EPHEMERAL) return val relay = Relay(RelayConfig(url, read = true, write = false), client, scope) @@ -1272,97 +1259,6 @@ class RelayPool(private val prefs: SharedPreferences? = null) { } } - // --- Local relay management --- - - fun updateLocalRelay(config: LocalRelayConfig?, userPubkey: String?) { - localRelayUserPubkey = userPubkey - val oldRelay = localRelay - val oldUrl = oldRelay?.config?.url - - if (config == null || !config.enabled) { - // Remove local relay - if (oldRelay != null) { - oldRelay.forceDisconnect() - cancelRelayJobs(oldRelay.config.url) - relayIndex.remove(oldRelay.config.url) - localRelay = null - localRelayConfig = null - Log.d("RLC", "[Pool] local relay removed: $oldUrl") - } - return - } - - localRelayConfig = config - - if (oldUrl == config.url && oldRelay != null) { - // URL unchanged — just update config, reconnect if needed. - // Re-enable auto-reconnect in case the relay was paused via pauseLocalRelay(). - oldRelay.reconnectEnabled = true - if (!oldRelay.isConnected) oldRelay.connect() - return - } - - // Disconnect old if URL changed - if (oldRelay != null) { - oldRelay.forceDisconnect() - cancelRelayJobs(oldRelay.config.url) - relayIndex.remove(oldRelay.config.url) - } - - // Create new local relay connection - val relayConfig = RelayConfig(config.url, read = true, write = true) - val relay = Relay(relayConfig, client) - localRelay = relay - relayIndex[config.url] = relay - collectMessages(relay) - - relay.connect() - Log.d("RLC", "[Pool] local relay connected: ${config.url}") - } - - /** Disconnect local relay socket but preserve references for cheap resume. */ - fun pauseLocalRelay() { - val relay = localRelay ?: return - relay.reconnectEnabled = false - relay.disconnect() - Log.d("RLC", "[Pool] local relay paused: ${relay.config.url}") - } - - /** Reconnect local relay if still configured and enabled. Safe to call repeatedly. */ - fun resumeLocalRelay() { - val relay = localRelay ?: return - val cfg = localRelayConfig ?: return - if (!cfg.enabled) return - relay.reconnectEnabled = true - relay.resetBackoff() - if (!relay.isConnected) relay.connect() - Log.d("RLC", "[Pool] local relay resumed: ${relay.config.url}") - } - - fun getLocalRelayUrl(): String? = localRelayConfig?.url - - /** Send a message to the local relay if configured and connected. Fire-and-forget. */ - fun sendToLocalRelay(message: String): Boolean { - val relay = localRelay ?: return false - if (localRelayConfig?.enabled != true) return false - return relay.send(message) - } - - private fun shouldForwardToLocalRelay(event: NostrEvent): Boolean { - val config = localRelayConfig ?: return false - if (!config.enabled) return false - if (localRelay == null) return false - if (event.kind !in config.kinds) return false - return when (config.writePolicy) { - LocalRelayWritePolicy.OWN_NOTES -> event.pubkey == localRelayUserPubkey - LocalRelayWritePolicy.TAGGED -> { - event.pubkey == localRelayUserPubkey || - event.tags.any { it.size >= 2 && it[0] == "p" && it[1] == localRelayUserPubkey } - } - LocalRelayWritePolicy.ALL_NOTES -> true - } - } - fun disconnectAll() { relays.forEach { it.forceDisconnect() } relays.clear() @@ -1374,9 +1270,6 @@ class RelayPool(private val prefs: SharedPreferences? = null) { ephemeralRelays.clear() ephemeralLastUsed.clear() relayCooldowns.clear() - localRelay?.forceDisconnect() - localRelay = null - localRelayConfig = null relayIndex.clear() relayJobs.values.forEach { it.cancel() } relayJobs.clear()