fix: prefer loopback for auto bind fallback
This commit is contained in:
@@ -148,6 +148,27 @@ actor GatewayConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let nsError = lastError as NSError
|
||||||
|
if nsError.domain == URLError.errorDomain,
|
||||||
|
let fallback = await GatewayEndpointStore.shared.maybeFallbackToTailnet(from: cfg.url)
|
||||||
|
{
|
||||||
|
await self.configure(url: fallback.url, token: fallback.token, password: fallback.password)
|
||||||
|
for delayMs in [150, 400, 900] {
|
||||||
|
try await Task.sleep(nanoseconds: UInt64(delayMs) * 1_000_000)
|
||||||
|
do {
|
||||||
|
guard let client = self.client else {
|
||||||
|
throw NSError(
|
||||||
|
domain: "Gateway",
|
||||||
|
code: 0,
|
||||||
|
userInfo: [NSLocalizedDescriptionKey: "gateway not configured"])
|
||||||
|
}
|
||||||
|
return try await client.request(method: method, params: params, timeoutMs: timeoutMs)
|
||||||
|
} catch {
|
||||||
|
lastError = error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
throw lastError
|
throw lastError
|
||||||
case .remote:
|
case .remote:
|
||||||
let nsError = error as NSError
|
let nsError = error as NSError
|
||||||
|
|||||||
@@ -469,6 +469,35 @@ actor GatewayEndpointStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func maybeFallbackToTailnet(from currentURL: URL) async -> GatewayConnection.Config? {
|
||||||
|
let mode = await self.deps.mode()
|
||||||
|
guard mode == .local else { return nil }
|
||||||
|
|
||||||
|
let root = ClawdbotConfigFile.loadDict()
|
||||||
|
let bind = GatewayEndpointStore.resolveGatewayBindMode(
|
||||||
|
root: root,
|
||||||
|
env: ProcessInfo.processInfo.environment)
|
||||||
|
guard bind == "auto" else { return nil }
|
||||||
|
|
||||||
|
let currentHost = currentURL.host?.lowercased() ?? ""
|
||||||
|
guard currentHost == "127.0.0.1" || currentHost == "localhost" else { return nil }
|
||||||
|
|
||||||
|
let tailscaleIP = await MainActor.run { TailscaleService.shared.tailscaleIP }
|
||||||
|
guard let tailscaleIP, !tailscaleIP.isEmpty else { return nil }
|
||||||
|
|
||||||
|
let scheme = GatewayEndpointStore.resolveGatewayScheme(
|
||||||
|
root: root,
|
||||||
|
env: ProcessInfo.processInfo.environment)
|
||||||
|
let port = self.deps.localPort()
|
||||||
|
let token = self.deps.token()
|
||||||
|
let password = self.deps.password()
|
||||||
|
let url = URL(string: "\(scheme)://\(tailscaleIP):\(port)")!
|
||||||
|
|
||||||
|
self.logger.info("auto bind fallback to tailnet host=\(tailscaleIP, privacy: .public)")
|
||||||
|
self.setState(.ready(mode: .local, url: url, token: token, password: password))
|
||||||
|
return (url, token, password)
|
||||||
|
}
|
||||||
|
|
||||||
private static func resolveGatewayBindMode(
|
private static func resolveGatewayBindMode(
|
||||||
root: [String: Any],
|
root: [String: Any],
|
||||||
env: [String: String]) -> String?
|
env: [String: String]) -> String?
|
||||||
@@ -524,8 +553,10 @@ actor GatewayEndpointStore {
|
|||||||
tailscaleIP: String?) -> String
|
tailscaleIP: String?) -> String
|
||||||
{
|
{
|
||||||
switch bindMode {
|
switch bindMode {
|
||||||
case "tailnet", "auto":
|
case "tailnet":
|
||||||
tailscaleIP ?? "127.0.0.1"
|
tailscaleIP ?? "127.0.0.1"
|
||||||
|
case "auto":
|
||||||
|
"127.0.0.1"
|
||||||
case "custom":
|
case "custom":
|
||||||
customBindHost ?? "127.0.0.1"
|
customBindHost ?? "127.0.0.1"
|
||||||
default:
|
default:
|
||||||
|
|||||||
Reference in New Issue
Block a user