damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

commit d074d092a267c8e5ada86eb083165778150af87d
parent 633fcd69a8f502adda08a1d1db98168110ddab96
Author: William Casarin <jb55@jb55.com>
Date:   Tue, 25 Apr 2023 15:06:09 -0700

Fix crash when you have invalid relays in your relay list

Changelog-Fixed: Fix crash when you have invalid relays in your relay list

Diffstat:
Mdamus.xcodeproj/project.pbxproj | 4----
Mdamus/ContentView.swift | 2+-
Mdamus/Models/Contacts.swift | 2+-
Mdamus/Models/HomeModel.swift | 6+++---
Ddamus/Models/LocalUserConfig.swift | 14--------------
Mdamus/Nostr/NostrEvent.swift | 2+-
Mdamus/Nostr/Relay.swift | 8++++----
Mdamus/Nostr/RelayConnection.swift | 30+++++++++++++++++++++++++++---
Mdamus/Nostr/RelayPool.swift | 10++++++----
Mdamus/Util/PostBox.swift | 4+---
Mdamus/Util/Relays/RelayFilters.swift | 2+-
Mdamus/Views/RelayFilterView.swift | 4++--
Mdamus/Views/Relays/RelayConfigView.swift | 8++++----
13 files changed, 51 insertions(+), 45 deletions(-)

diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj @@ -121,7 +121,6 @@ 4C5F9118283D88E40052CD1C /* FollowingModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C5F9117283D88E40052CD1C /* FollowingModel.swift */; }; 4C633350283D40E500B1C9C3 /* HomeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C63334F283D40E500B1C9C3 /* HomeModel.swift */; }; 4C633352283D419F00B1C9C3 /* SignalModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C633351283D419F00B1C9C3 /* SignalModel.swift */; }; - 4C649844285A952100EAE2B3 /* LocalUserConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C649843285A952100EAE2B3 /* LocalUserConfig.swift */; }; 4C64987C286D03E000EAE2B3 /* DirectMessagesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C64987B286D03E000EAE2B3 /* DirectMessagesView.swift */; }; 4C64987E286D082C00EAE2B3 /* DirectMessagesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C64987D286D082C00EAE2B3 /* DirectMessagesModel.swift */; }; 4C649881286E0EE300EAE2B3 /* secp256k1 in Frameworks */ = {isa = PBXBuildFile; productRef = 4C649880286E0EE300EAE2B3 /* secp256k1 */; }; @@ -530,7 +529,6 @@ 4C5F9117283D88E40052CD1C /* FollowingModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowingModel.swift; sourceTree = "<group>"; }; 4C63334F283D40E500B1C9C3 /* HomeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeModel.swift; sourceTree = "<group>"; }; 4C633351283D419F00B1C9C3 /* SignalModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignalModel.swift; sourceTree = "<group>"; }; - 4C649843285A952100EAE2B3 /* LocalUserConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalUserConfig.swift; sourceTree = "<group>"; }; 4C64987B286D03E000EAE2B3 /* DirectMessagesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DirectMessagesView.swift; sourceTree = "<group>"; }; 4C64987D286D082C00EAE2B3 /* DirectMessagesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DirectMessagesModel.swift; sourceTree = "<group>"; }; 4C75EFA327FA577B0006080F /* PostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostView.swift; sourceTree = "<group>"; }; @@ -837,7 +835,6 @@ 4C5F9117283D88E40052CD1C /* FollowingModel.swift */, 4C987B56283FD07F0042CE38 /* FollowersModel.swift */, 4C5C7E67284ED36500A22DF5 /* SearchHomeModel.swift */, - 4C649843285A952100EAE2B3 /* LocalUserConfig.swift */, 4C64987D286D082C00EAE2B3 /* DirectMessagesModel.swift */, 4C216F372871EDE300040376 /* DirectMessageModel.swift */, 4C99737A28C92A9200E53835 /* ChatroomMetadata.swift */, @@ -1572,7 +1569,6 @@ 4C8D00CA29DF80350036AF10 /* TruncatedText.swift in Sources */, 4C9BB83429C12D9900FC4E37 /* EventProfileName.swift in Sources */, 4CB8838F296F781C00DC99E7 /* ReactionsView.swift in Sources */, - 4C649844285A952100EAE2B3 /* LocalUserConfig.swift in Sources */, 4C75EFB328049D640006080F /* NostrEvent.swift in Sources */, 4CA2EFA0280E37AC0044ACD8 /* TimelineView.swift in Sources */, 4C30AC7629A5770900E2BD5A /* NotificationItemView.swift in Sources */, diff --git a/damus/ContentView.swift b/damus/ContentView.swift @@ -629,7 +629,7 @@ struct ContentView: View { let new_relay_filters = load_relay_filters(pubkey) == nil for relay in bootstrap_relays { - if let url = URL(string: relay) { + if let url = RelayURL(relay) { add_new_relay(relay_filters: relay_filters, metadatas: metadatas, pool: pool, url: url, info: .rw, new_relay_filters: new_relay_filters) } } diff --git a/damus/Models/Contacts.swift b/damus/Models/Contacts.swift @@ -242,7 +242,7 @@ func follow_with_existing_contacts(our_pubkey: String, our_contacts: NostrEvent, func make_contact_relays(_ relays: [RelayDescriptor]) -> [String: RelayInfo] { return relays.reduce(into: [:]) { acc, relay in - acc[relay.url.absoluteString] = relay.info + acc[relay.url.url.absoluteString] = relay.info } } diff --git a/damus/Models/HomeModel.swift b/damus/Models/HomeModel.swift @@ -809,7 +809,7 @@ func load_our_relays(state: DamusState, m_old_ev: NostrEvent?, ev: NostrEvent) { for d in diff { changed = true if new.contains(d) { - if let url = URL(string: d) { + if let url = RelayURL(d) { add_new_relay(relay_filters: state.relay_filters, metadatas: state.relay_metadata, pool: state.pool, url: url, info: decoded[d] ?? .rw, new_relay_filters: new_relay_filters) } } else { @@ -823,10 +823,10 @@ func load_our_relays(state: DamusState, m_old_ev: NostrEvent?, ev: NostrEvent) { } } -func add_new_relay(relay_filters: RelayFilters, metadatas: RelayMetadatas, pool: RelayPool, url: URL, info: RelayInfo, new_relay_filters: Bool) { +func add_new_relay(relay_filters: RelayFilters, metadatas: RelayMetadatas, pool: RelayPool, url: RelayURL, info: RelayInfo, new_relay_filters: Bool) { try? pool.add_relay(url, info: info) - let relay_id = url.absoluteString + let relay_id = url.id guard metadatas.lookup(relay_id: relay_id) == nil else { return } diff --git a/damus/Models/LocalUserConfig.swift b/damus/Models/LocalUserConfig.swift @@ -1,14 +0,0 @@ -// -// LocalUserConfig.swift -// damus -// -// Created by William Casarin on 2022-06-15. -// - -import Foundation - - -struct LocalUserConfig: Codable { - let relays: [RelayDescriptor] -} - diff --git a/damus/Nostr/NostrEvent.swift b/damus/Nostr/NostrEvent.swift @@ -694,7 +694,7 @@ func generate_private_keypair(our_privkey: String, id: String, created_at: Int64 func make_zap_request_event(keypair: FullKeypair, content: String, relays: [RelayDescriptor], target: ZapTarget, zap_type: ZapType) -> NostrEvent? { var tags = zap_target_to_tags(target) var relay_tag = ["relays"] - relay_tag.append(contentsOf: relays.map { $0.url.absoluteString }) + relay_tag.append(contentsOf: relays.map { $0.url.id }) tags.append(relay_tag) var kp = keypair diff --git a/damus/Nostr/Relay.swift b/damus/Nostr/Relay.swift @@ -14,8 +14,8 @@ public struct RelayInfo: Codable { static let rw = RelayInfo(read: true, write: true) } -public struct RelayDescriptor: Codable { - public let url: URL +public struct RelayDescriptor { + public let url: RelayURL public let info: RelayInfo } @@ -79,6 +79,6 @@ enum RelayError: Error { case RelayNotFound } -func get_relay_id(_ url: URL) -> String { - return url.absoluteString +func get_relay_id(_ url: RelayURL) -> String { + return url.url.absoluteString } diff --git a/damus/Nostr/RelayConnection.swift b/damus/Nostr/RelayConnection.swift @@ -13,18 +13,42 @@ enum NostrConnectionEvent { case nostr_event(NostrResponse) } +public struct RelayURL: Hashable { + private(set) var url: URL + + var id: String { + return url.absoluteString + } + + init?(_ str: String) { + guard let url = URL(string: str) else { + return nil + } + + guard let scheme = url.scheme else { + return nil + } + + guard scheme == "ws" || scheme == "wss" else { + return nil + } + + self.url = url + } +} + final class RelayConnection { private(set) var isConnected = false private(set) var isConnecting = false private(set) var last_connection_attempt: TimeInterval = 0 - private lazy var socket = WebSocket(url) + private lazy var socket = WebSocket(url.url) private var subscriptionToken: AnyCancellable? private var handleEvent: (NostrConnectionEvent) -> () - private let url: URL + private let url: RelayURL - init(url: URL, handleEvent: @escaping (NostrConnectionEvent) -> ()) { + init(url: RelayURL, handleEvent: @escaping (NostrConnectionEvent) -> ()) { self.url = url self.handleEvent = handleEvent } diff --git a/damus/Nostr/RelayPool.swift b/damus/Nostr/RelayPool.swift @@ -106,7 +106,7 @@ class RelayPool { } } - func add_relay(_ url: URL, info: RelayInfo) throws { + func add_relay(_ url: RelayURL, info: RelayInfo) throws { let relay_id = get_relay_id(url) if get_relay(relay_id) != nil { throw RelayError.RelayAlreadyExists @@ -127,7 +127,7 @@ class RelayPool { let is_connecting = c.isConnecting if is_connecting && (Date.now.timeIntervalSince1970 - c.last_connection_attempt) > 5 { - print("stale connection detected (\(relay.descriptor.url.absoluteString)). retrying...") + print("stale connection detected (\(relay.descriptor.url.url.absoluteString)). retrying...") relay.connection.reconnect() } else if relay.is_broken || is_connecting || c.isConnected { continue @@ -271,8 +271,10 @@ class RelayPool { } func add_rw_relay(_ pool: RelayPool, _ url: String) { - let url_ = URL(string: url)! - try? pool.add_relay(url_, info: RelayInfo.rw) + guard let url = RelayURL(url) else { + return + } + try? pool.add_relay(url, info: RelayInfo.rw) } diff --git a/damus/Util/PostBox.swift b/damus/Util/PostBox.swift @@ -109,9 +109,7 @@ class PostBox { return } - let remaining = pool.descriptors.map { - $0.url.absoluteString - } + let remaining = pool.descriptors.map { $0.url.id } let posted_ev = PostedEvent(event: event, remaining: remaining) events[event.id] = posted_ev diff --git a/damus/Util/Relays/RelayFilters.swift b/damus/Util/Relays/RelayFilters.swift @@ -89,6 +89,6 @@ func load_relay_filters(_ pubkey: String) -> Set<RelayFilter>? { func determine_to_relays(pool: RelayPool, filters: RelayFilters) -> [String] { return pool.descriptors - .map { $0.url.absoluteString } + .map { $0.url.url.absoluteString } .filter { !filters.is_filtered(timeline: .search, relay_id: $0) } } diff --git a/damus/Views/RelayFilterView.swift b/damus/Views/RelayFilterView.swift @@ -31,8 +31,8 @@ struct RelayFilterView: View { .padding(.top, 20) .padding(.bottom, 0) - List(Array(relays), id: \.url) { relay in - RelayToggle(state: state, timeline: timeline, relay_id: relay.url.absoluteString) + List(Array(relays), id: \.url.id) { relay in + RelayToggle(state: state, timeline: timeline, relay_id: relay.url.url.absoluteString) } } } diff --git a/damus/Views/Relays/RelayConfigView.swift b/damus/Views/Relays/RelayConfigView.swift @@ -23,7 +23,7 @@ struct RelayConfigView: View { var recommended: [RelayDescriptor] { let rs: [RelayDescriptor] = [] return BOOTSTRAP_RELAYS.reduce(into: rs) { xs, x in - if state.pool.get_relay(x) == nil, let url = URL(string: x) { + if state.pool.get_relay(x) == nil, let url = RelayURL(x) { xs.append(RelayDescriptor(url: url, info: .rw)) } } @@ -75,7 +75,7 @@ struct RelayConfigView: View { new_relay.removeLast(); } - guard let url = URL(string: new_relay) else { + guard let url = RelayURL(new_relay) else { return } @@ -120,7 +120,7 @@ struct RelayConfigView: View { Section { List(Array(relays), id: \.url) { relay in - RelayView(state: state, relay: relay.url.absoluteString, showActionButtons: $showActionButtons) + RelayView(state: state, relay: relay.url.id, showActionButtons: $showActionButtons) } } header: { HStack { @@ -133,7 +133,7 @@ struct RelayConfigView: View { if recommended.count > 0 { Section { List(recommended, id: \.url) { r in - RecommendedRelayView(damus: state, relay: r.url.absoluteString, showActionButtons: $showActionButtons) + RecommendedRelayView(damus: state, relay: r.url.id, showActionButtons: $showActionButtons) } } header: { Text(NSLocalizedString("Recommended Relays", comment: "Section title for recommend relay servers that could be added as part of configuration"))