From d159602928146fb7f08e987a56cff343181bbb46 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 20 Dec 2025 19:53:08 +0100 Subject: [PATCH] refactor: centralize gateway parsing --- .../Clawdis/GatewayDiscoveryMenu.swift | 9 +-- .../Clawdis/GatewayDiscoveryModel.swift | 76 +++++++++++-------- .../Sources/Clawdis/GeneralSettings.swift | 9 +-- apps/macos/Sources/Clawdis/Onboarding.swift | 9 +-- 4 files changed, 58 insertions(+), 45 deletions(-) diff --git a/apps/macos/Sources/Clawdis/GatewayDiscoveryMenu.swift b/apps/macos/Sources/Clawdis/GatewayDiscoveryMenu.swift index 2e77c2158..0aa3784a3 100644 --- a/apps/macos/Sources/Clawdis/GatewayDiscoveryMenu.swift +++ b/apps/macos/Sources/Clawdis/GatewayDiscoveryMenu.swift @@ -89,11 +89,10 @@ struct GatewayDiscoveryInlineList: View { let host = self.sanitizedTailnetHost(gateway.tailnetDns) ?? gateway.lanHost guard let host else { return nil } let user = NSUserName() - var target = "\(user)@\(host)" - if gateway.sshPort != 22 { - target += ":\(gateway.sshPort)" - } - return target + return GatewayDiscoveryModel.buildSSHTarget( + user: user, + host: host, + port: gateway.sshPort) } private func sanitizedTailnetHost(_ host: String?) -> String? { diff --git a/apps/macos/Sources/Clawdis/GatewayDiscoveryModel.swift b/apps/macos/Sources/Clawdis/GatewayDiscoveryModel.swift index 33545fba4..e3d2d0abc 100644 --- a/apps/macos/Sources/Clawdis/GatewayDiscoveryModel.swift +++ b/apps/macos/Sources/Clawdis/GatewayDiscoveryModel.swift @@ -117,31 +117,9 @@ final class GatewayDiscoveryModel { let prettyName = advertisedName ?? Self.prettifyServiceName(decodedName) - var lanHost: String? - var tailnetDns: String? - var sshPort = 22 - var cliPath: String? + let parsedTXT = Self.parseGatewayTXT(txt) - if let value = txt["lanHost"] { - let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) - lanHost = trimmed.isEmpty ? nil : trimmed - } - if let value = txt["tailnetDns"] { - let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) - tailnetDns = trimmed.isEmpty ? nil : trimmed - } - if let value = txt["sshPort"], - let parsed = Int(value.trimmingCharacters(in: .whitespacesAndNewlines)), - parsed > 0 - { - sshPort = parsed - } - if let value = txt["cliPath"] { - let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) - cliPath = trimmed.isEmpty ? nil : trimmed - } - - if lanHost == nil || tailnetDns == nil { + if parsedTXT.lanHost == nil || parsedTXT.tailnetDns == nil { self.ensureTXTResolution( stableID: stableID, serviceName: name, @@ -150,17 +128,17 @@ final class GatewayDiscoveryModel { } let isLocal = Self.isLocalGateway( - lanHost: lanHost, - tailnetDns: tailnetDns, + lanHost: parsedTXT.lanHost, + tailnetDns: parsedTXT.tailnetDns, displayName: prettyName, serviceName: decodedName, local: self.localIdentity) return DiscoveredGateway( displayName: prettyName, - lanHost: lanHost, - tailnetDns: tailnetDns, - sshPort: sshPort, - cliPath: cliPath, + lanHost: parsedTXT.lanHost, + tailnetDns: parsedTXT.tailnetDns, + sshPort: parsedTXT.sshPort, + cliPath: parsedTXT.cliPath, stableID: stableID, debugID: BridgeEndpointID.prettyDescription(result.endpoint), isLocal: isLocal) @@ -228,6 +206,44 @@ final class GatewayDiscoveryModel { return merged } + static func parseGatewayTXT(_ txt: [String: String]) + -> (lanHost: String?, tailnetDns: String?, sshPort: Int, cliPath: String?) + { + var lanHost: String? + var tailnetDns: String? + var sshPort = 22 + var cliPath: String? + + if let value = txt["lanHost"] { + let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) + lanHost = trimmed.isEmpty ? nil : trimmed + } + if let value = txt["tailnetDns"] { + let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) + tailnetDns = trimmed.isEmpty ? nil : trimmed + } + if let value = txt["sshPort"], + let parsed = Int(value.trimmingCharacters(in: .whitespacesAndNewlines)), + parsed > 0 + { + sshPort = parsed + } + if let value = txt["cliPath"] { + let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) + cliPath = trimmed.isEmpty ? nil : trimmed + } + + return (lanHost, tailnetDns, sshPort, cliPath) + } + + static func buildSSHTarget(user: String, host: String, port: Int) -> String { + var target = "\(user)@\(host)" + if port != 22 { + target += ":\(port)" + } + return target + } + private func ensureTXTResolution( stableID: String, serviceName: String, diff --git a/apps/macos/Sources/Clawdis/GeneralSettings.swift b/apps/macos/Sources/Clawdis/GeneralSettings.swift index 7a38cf814..def57e70a 100644 --- a/apps/macos/Sources/Clawdis/GeneralSettings.swift +++ b/apps/macos/Sources/Clawdis/GeneralSettings.swift @@ -612,11 +612,10 @@ extension GeneralSettings { let host = gateway.tailnetDns ?? gateway.lanHost guard let host else { return } let user = NSUserName() - var target = "\(user)@\(host)" - if gateway.sshPort != 22 { - target += ":\(gateway.sshPort)" - } - self.state.remoteTarget = target + self.state.remoteTarget = GatewayDiscoveryModel.buildSSHTarget( + user: user, + host: host, + port: gateway.sshPort) self.state.remoteCliPath = gateway.cliPath ?? "" } } diff --git a/apps/macos/Sources/Clawdis/Onboarding.swift b/apps/macos/Sources/Clawdis/Onboarding.swift index 2cd0ba04b..ab8156b61 100644 --- a/apps/macos/Sources/Clawdis/Onboarding.swift +++ b/apps/macos/Sources/Clawdis/Onboarding.swift @@ -454,11 +454,10 @@ struct OnboardingView: View { if let host = gateway.tailnetDns ?? gateway.lanHost { let user = NSUserName() - var target = "\(user)@\(host)" - if gateway.sshPort != 22 { - target += ":\(gateway.sshPort)" - } - self.state.remoteTarget = target + self.state.remoteTarget = GatewayDiscoveryModel.buildSSHTarget( + user: user, + host: host, + port: gateway.sshPort) } self.state.remoteCliPath = gateway.cliPath ?? ""