mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
fix(apple/macOS): Memoize successful SCDynamicStoreCreate (#7892)
Under some conditions the call to SCDynamicStoreCreate can fail, presumably due to some kind of allocation failure. Once it succeeds, however, we can continue using the dynamic store for the lifetime of the Adapter instance. So we memoize the result of this call so as not to allocate each time we need it. See https://developer.apple.com/documentation/systemconfiguration/1437828-scdynamicstorecreate
This commit is contained in:
@@ -58,6 +58,11 @@ class Adapter {
|
||||
private var gateways: [Network.NWEndpoint] = []
|
||||
#endif
|
||||
|
||||
#if os(macOS)
|
||||
/// Used for finding system DNS resolvers on macOS when network conditions have changed.
|
||||
private let systemConfigurationResolvers = SystemConfigurationResolvers()
|
||||
#endif
|
||||
|
||||
/// Track our last fetched DNS resolvers to know whether to tell connlib they've updated
|
||||
private var lastFetchedResolvers: [String] = []
|
||||
|
||||
@@ -453,7 +458,7 @@ extension Adapter: CallbackHandlerDelegate {
|
||||
|
||||
private func getSystemDefaultResolvers(interfaceName: String?) -> [String] {
|
||||
#if os(macOS)
|
||||
let resolvers = SystemConfigurationResolvers().getDefaultDNSServers(
|
||||
let resolvers = self.systemConfigurationResolvers.getDefaultDNSServers(
|
||||
interfaceName: interfaceName)
|
||||
#elseif os(iOS)
|
||||
let resolvers = resetToSystemDNSGettingBindResolvers()
|
||||
|
||||
@@ -26,23 +26,30 @@ class SystemConfigurationResolvers {
|
||||
}
|
||||
}
|
||||
}
|
||||
private var dynamicStore: SCDynamicStore?
|
||||
|
||||
/// We use a computed property to memoize the creation of SC Dynamic Store, since this
|
||||
/// can fail in some circumstances to initialize, like because of allocation failures.
|
||||
private var _dynamicStore: SCDynamicStore?
|
||||
private var dynamicStore: SCDynamicStore? {
|
||||
get {
|
||||
if self._dynamicStore == nil {
|
||||
guard let dynamicStore = SCDynamicStoreCreate(nil, storeName, nil, nil)
|
||||
else {
|
||||
let code = SCError()
|
||||
Log.error(SystemConfigurationError.failedToCreateDynamicStore(code: code))
|
||||
return nil
|
||||
}
|
||||
|
||||
self._dynamicStore = dynamicStore
|
||||
}
|
||||
|
||||
return self._dynamicStore
|
||||
}
|
||||
}
|
||||
|
||||
// Arbitrary name for the connection to the store
|
||||
private let storeName = "dev.firezone.firezone.dns" as CFString
|
||||
|
||||
init() {
|
||||
guard let dynamicStore = SCDynamicStoreCreate(nil, storeName, nil, nil)
|
||||
else {
|
||||
let code = SCError()
|
||||
Log.error(SystemConfigurationError.failedToCreateDynamicStore(code: code))
|
||||
self.dynamicStore = nil
|
||||
return
|
||||
}
|
||||
|
||||
self.dynamicStore = dynamicStore
|
||||
}
|
||||
|
||||
/// 1. First, find the service ID that corresponds to the interface we're interested in.
|
||||
/// We do this by searching the configuration store at "Setup:/Network/Service/<service-id>/Interface"
|
||||
/// for a matching "InterfaceName".
|
||||
|
||||
Reference in New Issue
Block a user